diff --git a/Makefile b/Makefile index d032459..20ccc14 100644 --- a/Makefile +++ b/Makefile @@ -45,13 +45,13 @@ test: .PHONY: install install: $(wildcard *.go) - CGO_ENABLED=0 go install -v -ldflags '-w $(LDFLAGS)' + go install -v -ldflags '-w $(LDFLAGS)' .PHONY: build build: $(EXECUTABLE) $(EXECUTABLE): $(SOURCES) - CGO_ENABLED=0 go build -v -ldflags '-w $(LDFLAGS)' -o $@ + go build -v -ldflags '-w $(LDFLAGS)' -o $@ .PHONY: docker docker: diff --git a/ana.go b/ana.go index 06dbc89..0a3a066 100644 --- a/ana.go +++ b/ana.go @@ -1,9 +1,9 @@ package main import ( - "github.com/dannyvankooten/ana/commands" - "github.com/dannyvankooten/ana/count" - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/commands" + "github.com/dannyvankooten/ana/pkg/count" + "github.com/dannyvankooten/ana/pkg/datastore" "github.com/joho/godotenv" "github.com/robfig/cron" "gopkg.in/alecthomas/kingpin.v2" diff --git a/assets/dist/css/styles.css b/assets/dist/css/styles.css new file mode 100644 index 0000000..996d027 --- /dev/null +++ b/assets/dist/css/styles.css @@ -0,0 +1,759 @@ +/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ +/** + * 1. Change the default font family in all browsers (opinionated). + * 2. Correct the line height in all browsers. + * 3. Prevent adjustments of font size after orientation changes in + * IE on Windows Phone and in iOS. + */ +/* Document + ========================================================================== */ +html { + font-family: sans-serif; + /* 1 */ + line-height: 1.15; + /* 2 */ + -ms-text-size-adjust: 100%; + /* 3 */ + -webkit-text-size-adjust: 100%; + /* 3 */ } + +/* Sections + ========================================================================== */ +/** + * Remove the margin in all browsers (opinionated). + */ +body { + margin: 0; } + +/** + * Add the correct display in IE 9-. + */ +article, +aside, +footer, +header, +nav, +section { + display: block; } + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ +h1 { + font-size: 2em; + margin: 0.67em 0; } + +/* Grouping content + ========================================================================== */ +/** + * Add the correct display in IE 9-. + * 1. Add the correct display in IE. + */ +figcaption, +figure, +main { + /* 1 */ + display: block; } + +/** + * Add the correct margin in IE 8. + */ +figure { + margin: 1em 40px; } + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ +hr { + box-sizing: content-box; + /* 1 */ + height: 0; + /* 1 */ + overflow: visible; + /* 2 */ } + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +pre { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ } + +/* Text-level semantics + ========================================================================== */ +/** + * 1. Remove the gray background on active links in IE 10. + * 2. Remove gaps in links underline in iOS 8+ and Safari 8+. + */ +a { + background-color: transparent; + /* 1 */ + -webkit-text-decoration-skip: objects; + /* 2 */ } + +/** + * Remove the outline on focused links when they are also active or hovered + * in all browsers (opinionated). + */ +a:active, +a:hover { + outline-width: 0; } + +/** + * 1. Remove the bottom border in Firefox 39-. + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ +abbr[title] { + border-bottom: none; + /* 1 */ + text-decoration: underline; + /* 2 */ + text-decoration: underline dotted; + /* 2 */ } + +/** + * Prevent the duplicate application of `bolder` by the next rule in Safari 6. + */ +b, +strong { + font-weight: inherit; } + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, +strong { + font-weight: bolder; } + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, +kbd, +samp { + font-family: monospace, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ } + +/** + * Add the correct font style in Android 4.3-. + */ +dfn { + font-style: italic; } + +/** + * Add the correct background and color in IE 9-. + */ +mark { + background-color: #ff0; + color: #000; } + +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; } + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; } + +sub { + bottom: -0.25em; } + +sup { + top: -0.5em; } + +/* Embedded content + ========================================================================== */ +/** + * Add the correct display in IE 9-. + */ +audio, +video { + display: inline-block; } + +/** + * Add the correct display in iOS 4-7. + */ +audio:not([controls]) { + display: none; + height: 0; } + +/** + * Remove the border on images inside links in IE 10-. + */ +img { + border-style: none; } + +/** + * Hide the overflow in IE. + */ +svg:not(:root) { + overflow: hidden; } + +/* Forms + ========================================================================== */ +/** + * 1. Change the font styles in all browsers (opinionated). + * 2. Remove the margin in Firefox and Safari. + */ +button, +input, +optgroup, +select, +textarea { + font-family: sans-serif; + /* 1 */ + font-size: 100%; + /* 1 */ + line-height: 1.15; + /* 1 */ + margin: 0; + /* 2 */ } + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ +button, +input { + /* 1 */ + overflow: visible; } + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, +select { + /* 1 */ + text-transform: none; } + +/** + * 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` + * controls in Android 4. + * 2. Correct the inability to style clickable types in iOS and Safari. + */ +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; + /* 2 */ } + +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; } + +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; } + +/** + * Change the border, margin, and padding in all browsers (opinionated). + */ +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; } + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ +legend { + box-sizing: border-box; + /* 1 */ + color: inherit; + /* 2 */ + display: table; + /* 1 */ + max-width: 100%; + /* 1 */ + padding: 0; + /* 3 */ + white-space: normal; + /* 1 */ } + +/** + * 1. Add the correct display in IE 9-. + * 2. Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ +progress { + display: inline-block; + /* 1 */ + vertical-align: baseline; + /* 2 */ } + +/** + * Remove the default vertical scrollbar in IE. + */ +textarea { + overflow: auto; } + +/** + * 1. Add the correct box sizing in IE 10-. + * 2. Remove the padding in IE 10-. + */ +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; + /* 1 */ + padding: 0; + /* 2 */ } + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; } + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type="search"] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ } + +/** + * Remove the inner padding and cancel buttons in Chrome and Safari on macOS. + */ +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; } + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ } + +/* Interactive + ========================================================================== */ +/* + * Add the correct display in IE 9-. + * 1. Add the correct display in Edge, IE, and Firefox. + */ +details, +menu { + display: block; } + +/* + * Add the correct display in all browsers. + */ +summary { + display: list-item; } + +/* Scripting + ========================================================================== */ +/** + * Add the correct display in IE 9-. + */ +canvas { + display: inline-block; } + +/** + * Add the correct display in IE. + */ +template { + display: none; } + +/* Hidden + ========================================================================== */ +/** + * Add the correct display in IE 10-. + */ +[hidden] { + display: none; } + +.pull-right { + float: right; } + +.pull-left { + float: left; } + +.cf:before, +.cf:after { + content: " "; + /* 1 */ + display: table; + /* 2 */ } + +.cf:after { + clear: both; } + +.tiny-margin { + margin-top: 10px; + margin-bottom: 10px; } + +.small-margin { + margin-top: 20px; + margin-bottom: 20px; } + +.medium-margin { + margin-top: 40px; + margin-bottom: 40px; } + +.no-margin { + margin: 0 !important; } + +.clear { + clear: both; } + +.big { + font-size: 32px; } + +.muted { + color: #888; } + +.italic { + font-style: italic; } + +.center-text { + text-align: center; } + +.positive { + color: limegreen; } + .positive:before { + content: "+"; } + +.negative { + color: orangered; } + +.inline { + display: inline-block; } + +.small-margin-right { + margin-right: 20px; } + +@media (min-width: 680px) { + .row { + margin-left: -10px; + margin-right: -10px; } + .row:before, .row:after { + content: " "; + display: table; } + .row:after { + clear: both; } + .col, + .col-1, + .col-2, + .col-3, + .col-4, + .col-5, + .col-6 { + float: left; + padding-left: 10px; + padding-right: 10px; + box-sizing: border-box; } + .col-1 { + width: 16.66667%; } + .col-2 { + width: 33.33333%; } + .col-3 { + width: 50%; } + .col-4 { + width: 66.66667%; } + .col-5 { + width: 83.33333%; } + .col-6 { + width: 100%; } } + +label { + font-weight: bold; + display: block; + margin-bottom: 2px; } + +input { + padding: 8px; + border: 1px solid #999; + min-width: 260px; } + input:focus { + border: 1px solid #33C3F0; + outline: 0; } + +input[type="checkbox"], +input[type="radio"] { + min-width: auto; + vertical-align: middle; + width: 16px; + height: 16px; } + +button, +input[type="submit"], +input[type="button"], +.button { + min-width: auto; + padding: 10px 20px; + cursor: pointer; + border: 0; + color: white; + background: #09F; + font-weight: bold; } + button.active, button:hover, button:focus, + input[type="submit"].active, + input[type="submit"]:hover, + input[type="submit"]:focus, + input[type="button"].active, + input[type="button"]:hover, + input[type="button"]:focus, + .button.active, + .button:hover, + .button:focus { + background: #005c99; } + +table { + width: 100%; + min-width: 100%; + border-collapse: collapse; } + table tbody > tr:nth-of-type(odd) { + background-color: #FAFAFA; } + table tbody > tr:hover { + background-color: #F6F6F6; } + table thead th { + border-top: 0; + border-bottom: 2px solid #ddd; } + table th { + color: #222; } + table th, table td { + text-align: left; + border-top: 1px solid #ddd; + padding: 8px; } + +* { + box-sizing: border-box; } + +body { + font-family: Raleway, HelveticaNeue, "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + color: #444; + background: #f5f5f5; } + +h1, h2, h3, h4, h5 { + color: #111; + margin: 0; } + h1 small, h2 small, h3 small, h4 small, h5 small { + font-weight: normal; + font-style: italic; + color: #666; } + +h5 { + font-size: 15px; } + +a { + color: #09f; + text-decoration: none; } + a:hover, a:focus { + text-decoration: underline; } + +.container { + max-width: 1020px; + padding: 0 20px; + margin-left: auto; + margin-right: auto; } + +.header { + margin: 20px 0; } + +.header-bar { + background: black; + color: white; + margin-bottom: 20px; + padding: 12px 0; + line-height: 32px; + font-weight: bold; } + .header-bar h1, .header-bar h2, .header-bar h3, .header-bar a { + color: white; } + .header-bar .subtitle { + color: #BBB; + margin-left: 10px; + font-size: 20px; } + +.block { + width: auto; + background: white; + padding: 20px; + margin-bottom: 20px; + position: relative; } + .block h1, .block h2, .block h3 { + margin-bottom: 20px; } + +.block-float { + margin-right: 20px; + float: left; } + +.loading-overlay { + position: absolute; + background: rgba(255, 255, 255, 0.9); + width: 100%; + height: 100%; + z-index: 10; + font-weight: bold; + margin: -20px; + display: flex; + align-items: center; + justify-content: center; } + .loading-overlay div { + margin: 50px; + height: 28px; + width: 28px; + animation: rotate 0.8s infinite linear; + border: 8px solid #AAA; + border-right-color: transparent; + border-radius: 50%; } + +@keyframes rotate { + 0% { + transform: rotate(0deg); } + 100% { + transform: rotate(360deg); } } + +.count { + font-weight: bold; + font-size: 120%; } + +.notification { + top: 20px; + left: 0; + right: 0; + text-align: center; + position: fixed; + color: white; } + .notification div { + color: white; + display: inline-block; + padding: 6px 12px; + background: green; } + .notification .notification-error { + background: red; } + +h1 { + font-size: 28px; } + +h2 { + font-size: 24px; } + +h3 { + font-size: 20px; } + +h4 { + font-size: 16px; } + +small { + font-size: 70%; } + +.d3-tip span { + color: #ff00c7; } + +.domain { + display: none; } + +.axis line { + stroke-width: 1px; + stroke: #eee; + shape-rendering: crispedges; } + +.axis text { + fill: #888; } + +rect { + fill: #66b5ff; + fill-opacity: 0.5; } + +rect:hover { + fill-opacity: 1; } + +.sub-bar rect { + fill: #0069cc; } + +.d3-tip { + line-height: 1; + font-weight: bold; + padding: 12px; + background: rgba(0, 0, 0, 0.8); + color: #fff; + border-radius: 2px; + pointer-events: none; } + +/* Creates a small triangle extender for the tooltip */ +.d3-tip:after { + box-sizing: border-box; + display: inline; + font-size: 10px; + width: 100%; + line-height: 1; + color: rgba(0, 0, 0, 0.8); + position: absolute; + pointer-events: none; } + +.d3-tip h5 { + color: #CCC; } + +.d3-tip span { + color: lightgreen; } + +/* Northward tooltips */ +.d3-tip.n:after { + content: "\25BC"; + margin: -1px 0 0 0; + top: 100%; + left: 0; + text-align: center; } + +/* Eastward tooltips */ +.d3-tip.e:after { + content: "\25C0"; + margin: -4px 0 0 0; + top: 50%; + left: -8px; } + +/* Southward tooltips */ +.d3-tip.s:after { + content: "\25B2"; + margin: 0 0 1px 0; + top: -8px; + left: 0; + text-align: center; } + +/* Westward tooltips */ +.d3-tip.w:after { + content: "\25B6"; + margin: -4px 0 0 -1px; + top: 50%; + left: 100%; } diff --git a/assets/img/country-flags/ad.png b/assets/dist/img/country-flags/ad.png similarity index 100% rename from assets/img/country-flags/ad.png rename to assets/dist/img/country-flags/ad.png diff --git a/assets/img/country-flags/ae.png b/assets/dist/img/country-flags/ae.png similarity index 100% rename from assets/img/country-flags/ae.png rename to assets/dist/img/country-flags/ae.png diff --git a/assets/img/country-flags/af.png b/assets/dist/img/country-flags/af.png similarity index 100% rename from assets/img/country-flags/af.png rename to assets/dist/img/country-flags/af.png diff --git a/assets/img/country-flags/ag.png b/assets/dist/img/country-flags/ag.png similarity index 100% rename from assets/img/country-flags/ag.png rename to assets/dist/img/country-flags/ag.png diff --git a/assets/img/country-flags/ai.png b/assets/dist/img/country-flags/ai.png similarity index 100% rename from assets/img/country-flags/ai.png rename to assets/dist/img/country-flags/ai.png diff --git a/assets/img/country-flags/al.png b/assets/dist/img/country-flags/al.png similarity index 100% rename from assets/img/country-flags/al.png rename to assets/dist/img/country-flags/al.png diff --git a/assets/img/country-flags/am.png b/assets/dist/img/country-flags/am.png similarity index 100% rename from assets/img/country-flags/am.png rename to assets/dist/img/country-flags/am.png diff --git a/assets/img/country-flags/ao.png b/assets/dist/img/country-flags/ao.png similarity index 100% rename from assets/img/country-flags/ao.png rename to assets/dist/img/country-flags/ao.png diff --git a/assets/img/country-flags/ar.png b/assets/dist/img/country-flags/ar.png similarity index 100% rename from assets/img/country-flags/ar.png rename to assets/dist/img/country-flags/ar.png diff --git a/assets/img/country-flags/as.png b/assets/dist/img/country-flags/as.png similarity index 100% rename from assets/img/country-flags/as.png rename to assets/dist/img/country-flags/as.png diff --git a/assets/img/country-flags/at.png b/assets/dist/img/country-flags/at.png similarity index 100% rename from assets/img/country-flags/at.png rename to assets/dist/img/country-flags/at.png diff --git a/assets/img/country-flags/au.png b/assets/dist/img/country-flags/au.png similarity index 100% rename from assets/img/country-flags/au.png rename to assets/dist/img/country-flags/au.png diff --git a/assets/img/country-flags/aw.png b/assets/dist/img/country-flags/aw.png similarity index 100% rename from assets/img/country-flags/aw.png rename to assets/dist/img/country-flags/aw.png diff --git a/assets/img/country-flags/ax.png b/assets/dist/img/country-flags/ax.png similarity index 100% rename from assets/img/country-flags/ax.png rename to assets/dist/img/country-flags/ax.png diff --git a/assets/img/country-flags/az.png b/assets/dist/img/country-flags/az.png similarity index 100% rename from assets/img/country-flags/az.png rename to assets/dist/img/country-flags/az.png diff --git a/assets/img/country-flags/ba.png b/assets/dist/img/country-flags/ba.png similarity index 100% rename from assets/img/country-flags/ba.png rename to assets/dist/img/country-flags/ba.png diff --git a/assets/img/country-flags/bb.png b/assets/dist/img/country-flags/bb.png similarity index 100% rename from assets/img/country-flags/bb.png rename to assets/dist/img/country-flags/bb.png diff --git a/assets/img/country-flags/bd.png b/assets/dist/img/country-flags/bd.png similarity index 100% rename from assets/img/country-flags/bd.png rename to assets/dist/img/country-flags/bd.png diff --git a/assets/img/country-flags/be.png b/assets/dist/img/country-flags/be.png similarity index 100% rename from assets/img/country-flags/be.png rename to assets/dist/img/country-flags/be.png diff --git a/assets/img/country-flags/bf.png b/assets/dist/img/country-flags/bf.png similarity index 100% rename from assets/img/country-flags/bf.png rename to assets/dist/img/country-flags/bf.png diff --git a/assets/img/country-flags/bg.png b/assets/dist/img/country-flags/bg.png similarity index 100% rename from assets/img/country-flags/bg.png rename to assets/dist/img/country-flags/bg.png diff --git a/assets/img/country-flags/bh.png b/assets/dist/img/country-flags/bh.png similarity index 100% rename from assets/img/country-flags/bh.png rename to assets/dist/img/country-flags/bh.png diff --git a/assets/img/country-flags/bi.png b/assets/dist/img/country-flags/bi.png similarity index 100% rename from assets/img/country-flags/bi.png rename to assets/dist/img/country-flags/bi.png diff --git a/assets/img/country-flags/bj.png b/assets/dist/img/country-flags/bj.png similarity index 100% rename from assets/img/country-flags/bj.png rename to assets/dist/img/country-flags/bj.png diff --git a/assets/img/country-flags/bm.png b/assets/dist/img/country-flags/bm.png similarity index 100% rename from assets/img/country-flags/bm.png rename to assets/dist/img/country-flags/bm.png diff --git a/assets/img/country-flags/bn.png b/assets/dist/img/country-flags/bn.png similarity index 100% rename from assets/img/country-flags/bn.png rename to assets/dist/img/country-flags/bn.png diff --git a/assets/img/country-flags/bo.png b/assets/dist/img/country-flags/bo.png similarity index 100% rename from assets/img/country-flags/bo.png rename to assets/dist/img/country-flags/bo.png diff --git a/assets/img/country-flags/br.png b/assets/dist/img/country-flags/br.png similarity index 100% rename from assets/img/country-flags/br.png rename to assets/dist/img/country-flags/br.png diff --git a/assets/img/country-flags/bs.png b/assets/dist/img/country-flags/bs.png similarity index 100% rename from assets/img/country-flags/bs.png rename to assets/dist/img/country-flags/bs.png diff --git a/assets/img/country-flags/bt.png b/assets/dist/img/country-flags/bt.png similarity index 100% rename from assets/img/country-flags/bt.png rename to assets/dist/img/country-flags/bt.png diff --git a/assets/img/country-flags/bw.png b/assets/dist/img/country-flags/bw.png similarity index 100% rename from assets/img/country-flags/bw.png rename to assets/dist/img/country-flags/bw.png diff --git a/assets/img/country-flags/by.png b/assets/dist/img/country-flags/by.png similarity index 100% rename from assets/img/country-flags/by.png rename to assets/dist/img/country-flags/by.png diff --git a/assets/img/country-flags/bz.png b/assets/dist/img/country-flags/bz.png similarity index 100% rename from assets/img/country-flags/bz.png rename to assets/dist/img/country-flags/bz.png diff --git a/assets/img/country-flags/ca.png b/assets/dist/img/country-flags/ca.png similarity index 100% rename from assets/img/country-flags/ca.png rename to assets/dist/img/country-flags/ca.png diff --git a/assets/img/country-flags/cc.png b/assets/dist/img/country-flags/cc.png similarity index 100% rename from assets/img/country-flags/cc.png rename to assets/dist/img/country-flags/cc.png diff --git a/assets/img/country-flags/cd.png b/assets/dist/img/country-flags/cd.png similarity index 100% rename from assets/img/country-flags/cd.png rename to assets/dist/img/country-flags/cd.png diff --git a/assets/img/country-flags/cf.png b/assets/dist/img/country-flags/cf.png similarity index 100% rename from assets/img/country-flags/cf.png rename to assets/dist/img/country-flags/cf.png diff --git a/assets/img/country-flags/cg.png b/assets/dist/img/country-flags/cg.png similarity index 100% rename from assets/img/country-flags/cg.png rename to assets/dist/img/country-flags/cg.png diff --git a/assets/img/country-flags/ch.png b/assets/dist/img/country-flags/ch.png similarity index 100% rename from assets/img/country-flags/ch.png rename to assets/dist/img/country-flags/ch.png diff --git a/assets/img/country-flags/ci.png b/assets/dist/img/country-flags/ci.png similarity index 100% rename from assets/img/country-flags/ci.png rename to assets/dist/img/country-flags/ci.png diff --git a/assets/img/country-flags/ck.png b/assets/dist/img/country-flags/ck.png similarity index 100% rename from assets/img/country-flags/ck.png rename to assets/dist/img/country-flags/ck.png diff --git a/assets/img/country-flags/cl.png b/assets/dist/img/country-flags/cl.png similarity index 100% rename from assets/img/country-flags/cl.png rename to assets/dist/img/country-flags/cl.png diff --git a/assets/img/country-flags/cm.png b/assets/dist/img/country-flags/cm.png similarity index 100% rename from assets/img/country-flags/cm.png rename to assets/dist/img/country-flags/cm.png diff --git a/assets/img/country-flags/cn.png b/assets/dist/img/country-flags/cn.png similarity index 100% rename from assets/img/country-flags/cn.png rename to assets/dist/img/country-flags/cn.png diff --git a/assets/img/country-flags/co.png b/assets/dist/img/country-flags/co.png similarity index 100% rename from assets/img/country-flags/co.png rename to assets/dist/img/country-flags/co.png diff --git a/assets/img/country-flags/cr.png b/assets/dist/img/country-flags/cr.png similarity index 100% rename from assets/img/country-flags/cr.png rename to assets/dist/img/country-flags/cr.png diff --git a/assets/img/country-flags/cu.png b/assets/dist/img/country-flags/cu.png similarity index 100% rename from assets/img/country-flags/cu.png rename to assets/dist/img/country-flags/cu.png diff --git a/assets/img/country-flags/cv.png b/assets/dist/img/country-flags/cv.png similarity index 100% rename from assets/img/country-flags/cv.png rename to assets/dist/img/country-flags/cv.png diff --git a/assets/img/country-flags/cw.png b/assets/dist/img/country-flags/cw.png similarity index 100% rename from assets/img/country-flags/cw.png rename to assets/dist/img/country-flags/cw.png diff --git a/assets/img/country-flags/cx.png b/assets/dist/img/country-flags/cx.png similarity index 100% rename from assets/img/country-flags/cx.png rename to assets/dist/img/country-flags/cx.png diff --git a/assets/img/country-flags/cy.png b/assets/dist/img/country-flags/cy.png similarity index 100% rename from assets/img/country-flags/cy.png rename to assets/dist/img/country-flags/cy.png diff --git a/assets/img/country-flags/cz.png b/assets/dist/img/country-flags/cz.png similarity index 100% rename from assets/img/country-flags/cz.png rename to assets/dist/img/country-flags/cz.png diff --git a/assets/img/country-flags/de.png b/assets/dist/img/country-flags/de.png similarity index 100% rename from assets/img/country-flags/de.png rename to assets/dist/img/country-flags/de.png diff --git a/assets/img/country-flags/dj.png b/assets/dist/img/country-flags/dj.png similarity index 100% rename from assets/img/country-flags/dj.png rename to assets/dist/img/country-flags/dj.png diff --git a/assets/img/country-flags/dk.png b/assets/dist/img/country-flags/dk.png similarity index 100% rename from assets/img/country-flags/dk.png rename to assets/dist/img/country-flags/dk.png diff --git a/assets/img/country-flags/dm.png b/assets/dist/img/country-flags/dm.png similarity index 100% rename from assets/img/country-flags/dm.png rename to assets/dist/img/country-flags/dm.png diff --git a/assets/img/country-flags/do.png b/assets/dist/img/country-flags/do.png similarity index 100% rename from assets/img/country-flags/do.png rename to assets/dist/img/country-flags/do.png diff --git a/assets/img/country-flags/dz.png b/assets/dist/img/country-flags/dz.png similarity index 100% rename from assets/img/country-flags/dz.png rename to assets/dist/img/country-flags/dz.png diff --git a/assets/img/country-flags/ec.png b/assets/dist/img/country-flags/ec.png similarity index 100% rename from assets/img/country-flags/ec.png rename to assets/dist/img/country-flags/ec.png diff --git a/assets/img/country-flags/ee.png b/assets/dist/img/country-flags/ee.png similarity index 100% rename from assets/img/country-flags/ee.png rename to assets/dist/img/country-flags/ee.png diff --git a/assets/img/country-flags/eg.png b/assets/dist/img/country-flags/eg.png similarity index 100% rename from assets/img/country-flags/eg.png rename to assets/dist/img/country-flags/eg.png diff --git a/assets/img/country-flags/er.png b/assets/dist/img/country-flags/er.png similarity index 100% rename from assets/img/country-flags/er.png rename to assets/dist/img/country-flags/er.png diff --git a/assets/img/country-flags/es.png b/assets/dist/img/country-flags/es.png similarity index 100% rename from assets/img/country-flags/es.png rename to assets/dist/img/country-flags/es.png diff --git a/assets/img/country-flags/et.png b/assets/dist/img/country-flags/et.png similarity index 100% rename from assets/img/country-flags/et.png rename to assets/dist/img/country-flags/et.png diff --git a/assets/img/country-flags/fi.png b/assets/dist/img/country-flags/fi.png similarity index 100% rename from assets/img/country-flags/fi.png rename to assets/dist/img/country-flags/fi.png diff --git a/assets/img/country-flags/fj.png b/assets/dist/img/country-flags/fj.png similarity index 100% rename from assets/img/country-flags/fj.png rename to assets/dist/img/country-flags/fj.png diff --git a/assets/img/country-flags/fk.png b/assets/dist/img/country-flags/fk.png similarity index 100% rename from assets/img/country-flags/fk.png rename to assets/dist/img/country-flags/fk.png diff --git a/assets/img/country-flags/fm.png b/assets/dist/img/country-flags/fm.png similarity index 100% rename from assets/img/country-flags/fm.png rename to assets/dist/img/country-flags/fm.png diff --git a/assets/img/country-flags/fo.png b/assets/dist/img/country-flags/fo.png similarity index 100% rename from assets/img/country-flags/fo.png rename to assets/dist/img/country-flags/fo.png diff --git a/assets/img/country-flags/fr.png b/assets/dist/img/country-flags/fr.png similarity index 100% rename from assets/img/country-flags/fr.png rename to assets/dist/img/country-flags/fr.png diff --git a/assets/img/country-flags/ga.png b/assets/dist/img/country-flags/ga.png similarity index 100% rename from assets/img/country-flags/ga.png rename to assets/dist/img/country-flags/ga.png diff --git a/assets/img/country-flags/gb.png b/assets/dist/img/country-flags/gb.png similarity index 100% rename from assets/img/country-flags/gb.png rename to assets/dist/img/country-flags/gb.png diff --git a/assets/img/country-flags/gd.png b/assets/dist/img/country-flags/gd.png similarity index 100% rename from assets/img/country-flags/gd.png rename to assets/dist/img/country-flags/gd.png diff --git a/assets/img/country-flags/ge.png b/assets/dist/img/country-flags/ge.png similarity index 100% rename from assets/img/country-flags/ge.png rename to assets/dist/img/country-flags/ge.png diff --git a/assets/img/country-flags/gg.png b/assets/dist/img/country-flags/gg.png similarity index 100% rename from assets/img/country-flags/gg.png rename to assets/dist/img/country-flags/gg.png diff --git a/assets/img/country-flags/gh.png b/assets/dist/img/country-flags/gh.png similarity index 100% rename from assets/img/country-flags/gh.png rename to assets/dist/img/country-flags/gh.png diff --git a/assets/img/country-flags/gi.png b/assets/dist/img/country-flags/gi.png similarity index 100% rename from assets/img/country-flags/gi.png rename to assets/dist/img/country-flags/gi.png diff --git a/assets/img/country-flags/gl.png b/assets/dist/img/country-flags/gl.png similarity index 100% rename from assets/img/country-flags/gl.png rename to assets/dist/img/country-flags/gl.png diff --git a/assets/img/country-flags/gm.png b/assets/dist/img/country-flags/gm.png similarity index 100% rename from assets/img/country-flags/gm.png rename to assets/dist/img/country-flags/gm.png diff --git a/assets/img/country-flags/gn.png b/assets/dist/img/country-flags/gn.png similarity index 100% rename from assets/img/country-flags/gn.png rename to assets/dist/img/country-flags/gn.png diff --git a/assets/img/country-flags/gq.png b/assets/dist/img/country-flags/gq.png similarity index 100% rename from assets/img/country-flags/gq.png rename to assets/dist/img/country-flags/gq.png diff --git a/assets/img/country-flags/gr.png b/assets/dist/img/country-flags/gr.png similarity index 100% rename from assets/img/country-flags/gr.png rename to assets/dist/img/country-flags/gr.png diff --git a/assets/img/country-flags/gs.png b/assets/dist/img/country-flags/gs.png similarity index 100% rename from assets/img/country-flags/gs.png rename to assets/dist/img/country-flags/gs.png diff --git a/assets/img/country-flags/gt.png b/assets/dist/img/country-flags/gt.png similarity index 100% rename from assets/img/country-flags/gt.png rename to assets/dist/img/country-flags/gt.png diff --git a/assets/img/country-flags/gu.png b/assets/dist/img/country-flags/gu.png similarity index 100% rename from assets/img/country-flags/gu.png rename to assets/dist/img/country-flags/gu.png diff --git a/assets/img/country-flags/gw.png b/assets/dist/img/country-flags/gw.png similarity index 100% rename from assets/img/country-flags/gw.png rename to assets/dist/img/country-flags/gw.png diff --git a/assets/img/country-flags/gy.png b/assets/dist/img/country-flags/gy.png similarity index 100% rename from assets/img/country-flags/gy.png rename to assets/dist/img/country-flags/gy.png diff --git a/assets/img/country-flags/hk.png b/assets/dist/img/country-flags/hk.png similarity index 100% rename from assets/img/country-flags/hk.png rename to assets/dist/img/country-flags/hk.png diff --git a/assets/img/country-flags/hn.png b/assets/dist/img/country-flags/hn.png similarity index 100% rename from assets/img/country-flags/hn.png rename to assets/dist/img/country-flags/hn.png diff --git a/assets/img/country-flags/hr.png b/assets/dist/img/country-flags/hr.png similarity index 100% rename from assets/img/country-flags/hr.png rename to assets/dist/img/country-flags/hr.png diff --git a/assets/img/country-flags/ht.png b/assets/dist/img/country-flags/ht.png similarity index 100% rename from assets/img/country-flags/ht.png rename to assets/dist/img/country-flags/ht.png diff --git a/assets/img/country-flags/hu.png b/assets/dist/img/country-flags/hu.png similarity index 100% rename from assets/img/country-flags/hu.png rename to assets/dist/img/country-flags/hu.png diff --git a/assets/img/country-flags/id.png b/assets/dist/img/country-flags/id.png similarity index 100% rename from assets/img/country-flags/id.png rename to assets/dist/img/country-flags/id.png diff --git a/assets/img/country-flags/ie.png b/assets/dist/img/country-flags/ie.png similarity index 100% rename from assets/img/country-flags/ie.png rename to assets/dist/img/country-flags/ie.png diff --git a/assets/img/country-flags/il.png b/assets/dist/img/country-flags/il.png similarity index 100% rename from assets/img/country-flags/il.png rename to assets/dist/img/country-flags/il.png diff --git a/assets/img/country-flags/im.png b/assets/dist/img/country-flags/im.png similarity index 100% rename from assets/img/country-flags/im.png rename to assets/dist/img/country-flags/im.png diff --git a/assets/img/country-flags/in.png b/assets/dist/img/country-flags/in.png similarity index 100% rename from assets/img/country-flags/in.png rename to assets/dist/img/country-flags/in.png diff --git a/assets/img/country-flags/io.png b/assets/dist/img/country-flags/io.png similarity index 100% rename from assets/img/country-flags/io.png rename to assets/dist/img/country-flags/io.png diff --git a/assets/img/country-flags/iq.png b/assets/dist/img/country-flags/iq.png similarity index 100% rename from assets/img/country-flags/iq.png rename to assets/dist/img/country-flags/iq.png diff --git a/assets/img/country-flags/ir.png b/assets/dist/img/country-flags/ir.png similarity index 100% rename from assets/img/country-flags/ir.png rename to assets/dist/img/country-flags/ir.png diff --git a/assets/img/country-flags/is.png b/assets/dist/img/country-flags/is.png similarity index 100% rename from assets/img/country-flags/is.png rename to assets/dist/img/country-flags/is.png diff --git a/assets/img/country-flags/it.png b/assets/dist/img/country-flags/it.png similarity index 100% rename from assets/img/country-flags/it.png rename to assets/dist/img/country-flags/it.png diff --git a/assets/img/country-flags/je.png b/assets/dist/img/country-flags/je.png similarity index 100% rename from assets/img/country-flags/je.png rename to assets/dist/img/country-flags/je.png diff --git a/assets/img/country-flags/jm.png b/assets/dist/img/country-flags/jm.png similarity index 100% rename from assets/img/country-flags/jm.png rename to assets/dist/img/country-flags/jm.png diff --git a/assets/img/country-flags/jo.png b/assets/dist/img/country-flags/jo.png similarity index 100% rename from assets/img/country-flags/jo.png rename to assets/dist/img/country-flags/jo.png diff --git a/assets/img/country-flags/jp.png b/assets/dist/img/country-flags/jp.png similarity index 100% rename from assets/img/country-flags/jp.png rename to assets/dist/img/country-flags/jp.png diff --git a/assets/img/country-flags/ke.png b/assets/dist/img/country-flags/ke.png similarity index 100% rename from assets/img/country-flags/ke.png rename to assets/dist/img/country-flags/ke.png diff --git a/assets/img/country-flags/kg.png b/assets/dist/img/country-flags/kg.png similarity index 100% rename from assets/img/country-flags/kg.png rename to assets/dist/img/country-flags/kg.png diff --git a/assets/img/country-flags/kh.png b/assets/dist/img/country-flags/kh.png similarity index 100% rename from assets/img/country-flags/kh.png rename to assets/dist/img/country-flags/kh.png diff --git a/assets/img/country-flags/ki.png b/assets/dist/img/country-flags/ki.png similarity index 100% rename from assets/img/country-flags/ki.png rename to assets/dist/img/country-flags/ki.png diff --git a/assets/img/country-flags/km.png b/assets/dist/img/country-flags/km.png similarity index 100% rename from assets/img/country-flags/km.png rename to assets/dist/img/country-flags/km.png diff --git a/assets/img/country-flags/kn.png b/assets/dist/img/country-flags/kn.png similarity index 100% rename from assets/img/country-flags/kn.png rename to assets/dist/img/country-flags/kn.png diff --git a/assets/img/country-flags/kp.png b/assets/dist/img/country-flags/kp.png similarity index 100% rename from assets/img/country-flags/kp.png rename to assets/dist/img/country-flags/kp.png diff --git a/assets/img/country-flags/kr.png b/assets/dist/img/country-flags/kr.png similarity index 100% rename from assets/img/country-flags/kr.png rename to assets/dist/img/country-flags/kr.png diff --git a/assets/img/country-flags/kw.png b/assets/dist/img/country-flags/kw.png similarity index 100% rename from assets/img/country-flags/kw.png rename to assets/dist/img/country-flags/kw.png diff --git a/assets/img/country-flags/ky.png b/assets/dist/img/country-flags/ky.png similarity index 100% rename from assets/img/country-flags/ky.png rename to assets/dist/img/country-flags/ky.png diff --git a/assets/img/country-flags/kz.png b/assets/dist/img/country-flags/kz.png similarity index 100% rename from assets/img/country-flags/kz.png rename to assets/dist/img/country-flags/kz.png diff --git a/assets/img/country-flags/la.png b/assets/dist/img/country-flags/la.png similarity index 100% rename from assets/img/country-flags/la.png rename to assets/dist/img/country-flags/la.png diff --git a/assets/img/country-flags/lb.png b/assets/dist/img/country-flags/lb.png similarity index 100% rename from assets/img/country-flags/lb.png rename to assets/dist/img/country-flags/lb.png diff --git a/assets/img/country-flags/lc.png b/assets/dist/img/country-flags/lc.png similarity index 100% rename from assets/img/country-flags/lc.png rename to assets/dist/img/country-flags/lc.png diff --git a/assets/img/country-flags/li.png b/assets/dist/img/country-flags/li.png similarity index 100% rename from assets/img/country-flags/li.png rename to assets/dist/img/country-flags/li.png diff --git a/assets/img/country-flags/lk.png b/assets/dist/img/country-flags/lk.png similarity index 100% rename from assets/img/country-flags/lk.png rename to assets/dist/img/country-flags/lk.png diff --git a/assets/img/country-flags/lr.png b/assets/dist/img/country-flags/lr.png similarity index 100% rename from assets/img/country-flags/lr.png rename to assets/dist/img/country-flags/lr.png diff --git a/assets/img/country-flags/ls.png b/assets/dist/img/country-flags/ls.png similarity index 100% rename from assets/img/country-flags/ls.png rename to assets/dist/img/country-flags/ls.png diff --git a/assets/img/country-flags/lt.png b/assets/dist/img/country-flags/lt.png similarity index 100% rename from assets/img/country-flags/lt.png rename to assets/dist/img/country-flags/lt.png diff --git a/assets/img/country-flags/lu.png b/assets/dist/img/country-flags/lu.png similarity index 100% rename from assets/img/country-flags/lu.png rename to assets/dist/img/country-flags/lu.png diff --git a/assets/img/country-flags/lv.png b/assets/dist/img/country-flags/lv.png similarity index 100% rename from assets/img/country-flags/lv.png rename to assets/dist/img/country-flags/lv.png diff --git a/assets/img/country-flags/ly.png b/assets/dist/img/country-flags/ly.png similarity index 100% rename from assets/img/country-flags/ly.png rename to assets/dist/img/country-flags/ly.png diff --git a/assets/img/country-flags/ma.png b/assets/dist/img/country-flags/ma.png similarity index 100% rename from assets/img/country-flags/ma.png rename to assets/dist/img/country-flags/ma.png diff --git a/assets/img/country-flags/mc.png b/assets/dist/img/country-flags/mc.png similarity index 100% rename from assets/img/country-flags/mc.png rename to assets/dist/img/country-flags/mc.png diff --git a/assets/img/country-flags/md.png b/assets/dist/img/country-flags/md.png similarity index 100% rename from assets/img/country-flags/md.png rename to assets/dist/img/country-flags/md.png diff --git a/assets/img/country-flags/me.png b/assets/dist/img/country-flags/me.png similarity index 100% rename from assets/img/country-flags/me.png rename to assets/dist/img/country-flags/me.png diff --git a/assets/img/country-flags/mg.png b/assets/dist/img/country-flags/mg.png similarity index 100% rename from assets/img/country-flags/mg.png rename to assets/dist/img/country-flags/mg.png diff --git a/assets/img/country-flags/mh.png b/assets/dist/img/country-flags/mh.png similarity index 100% rename from assets/img/country-flags/mh.png rename to assets/dist/img/country-flags/mh.png diff --git a/assets/img/country-flags/mk.png b/assets/dist/img/country-flags/mk.png similarity index 100% rename from assets/img/country-flags/mk.png rename to assets/dist/img/country-flags/mk.png diff --git a/assets/img/country-flags/ml.png b/assets/dist/img/country-flags/ml.png similarity index 100% rename from assets/img/country-flags/ml.png rename to assets/dist/img/country-flags/ml.png diff --git a/assets/img/country-flags/mm.png b/assets/dist/img/country-flags/mm.png similarity index 100% rename from assets/img/country-flags/mm.png rename to assets/dist/img/country-flags/mm.png diff --git a/assets/img/country-flags/mn.png b/assets/dist/img/country-flags/mn.png similarity index 100% rename from assets/img/country-flags/mn.png rename to assets/dist/img/country-flags/mn.png diff --git a/assets/img/country-flags/mo.png b/assets/dist/img/country-flags/mo.png similarity index 100% rename from assets/img/country-flags/mo.png rename to assets/dist/img/country-flags/mo.png diff --git a/assets/img/country-flags/mp.png b/assets/dist/img/country-flags/mp.png similarity index 100% rename from assets/img/country-flags/mp.png rename to assets/dist/img/country-flags/mp.png diff --git a/assets/img/country-flags/mq.png b/assets/dist/img/country-flags/mq.png similarity index 100% rename from assets/img/country-flags/mq.png rename to assets/dist/img/country-flags/mq.png diff --git a/assets/img/country-flags/mr.png b/assets/dist/img/country-flags/mr.png similarity index 100% rename from assets/img/country-flags/mr.png rename to assets/dist/img/country-flags/mr.png diff --git a/assets/img/country-flags/ms.png b/assets/dist/img/country-flags/ms.png similarity index 100% rename from assets/img/country-flags/ms.png rename to assets/dist/img/country-flags/ms.png diff --git a/assets/img/country-flags/mt.png b/assets/dist/img/country-flags/mt.png similarity index 100% rename from assets/img/country-flags/mt.png rename to assets/dist/img/country-flags/mt.png diff --git a/assets/img/country-flags/mu.png b/assets/dist/img/country-flags/mu.png similarity index 100% rename from assets/img/country-flags/mu.png rename to assets/dist/img/country-flags/mu.png diff --git a/assets/img/country-flags/mv.png b/assets/dist/img/country-flags/mv.png similarity index 100% rename from assets/img/country-flags/mv.png rename to assets/dist/img/country-flags/mv.png diff --git a/assets/img/country-flags/mw.png b/assets/dist/img/country-flags/mw.png similarity index 100% rename from assets/img/country-flags/mw.png rename to assets/dist/img/country-flags/mw.png diff --git a/assets/img/country-flags/mx.png b/assets/dist/img/country-flags/mx.png similarity index 100% rename from assets/img/country-flags/mx.png rename to assets/dist/img/country-flags/mx.png diff --git a/assets/img/country-flags/my.png b/assets/dist/img/country-flags/my.png similarity index 100% rename from assets/img/country-flags/my.png rename to assets/dist/img/country-flags/my.png diff --git a/assets/img/country-flags/mz.png b/assets/dist/img/country-flags/mz.png similarity index 100% rename from assets/img/country-flags/mz.png rename to assets/dist/img/country-flags/mz.png diff --git a/assets/img/country-flags/na.png b/assets/dist/img/country-flags/na.png similarity index 100% rename from assets/img/country-flags/na.png rename to assets/dist/img/country-flags/na.png diff --git a/assets/img/country-flags/nc.png b/assets/dist/img/country-flags/nc.png similarity index 100% rename from assets/img/country-flags/nc.png rename to assets/dist/img/country-flags/nc.png diff --git a/assets/img/country-flags/ne.png b/assets/dist/img/country-flags/ne.png similarity index 100% rename from assets/img/country-flags/ne.png rename to assets/dist/img/country-flags/ne.png diff --git a/assets/img/country-flags/nf.png b/assets/dist/img/country-flags/nf.png similarity index 100% rename from assets/img/country-flags/nf.png rename to assets/dist/img/country-flags/nf.png diff --git a/assets/img/country-flags/ng.png b/assets/dist/img/country-flags/ng.png similarity index 100% rename from assets/img/country-flags/ng.png rename to assets/dist/img/country-flags/ng.png diff --git a/assets/img/country-flags/ni.png b/assets/dist/img/country-flags/ni.png similarity index 100% rename from assets/img/country-flags/ni.png rename to assets/dist/img/country-flags/ni.png diff --git a/assets/img/country-flags/nl.png b/assets/dist/img/country-flags/nl.png similarity index 100% rename from assets/img/country-flags/nl.png rename to assets/dist/img/country-flags/nl.png diff --git a/assets/img/country-flags/no.png b/assets/dist/img/country-flags/no.png similarity index 100% rename from assets/img/country-flags/no.png rename to assets/dist/img/country-flags/no.png diff --git a/assets/img/country-flags/np.png b/assets/dist/img/country-flags/np.png similarity index 100% rename from assets/img/country-flags/np.png rename to assets/dist/img/country-flags/np.png diff --git a/assets/img/country-flags/nr.png b/assets/dist/img/country-flags/nr.png similarity index 100% rename from assets/img/country-flags/nr.png rename to assets/dist/img/country-flags/nr.png diff --git a/assets/img/country-flags/nu.png b/assets/dist/img/country-flags/nu.png similarity index 100% rename from assets/img/country-flags/nu.png rename to assets/dist/img/country-flags/nu.png diff --git a/assets/img/country-flags/nz.png b/assets/dist/img/country-flags/nz.png similarity index 100% rename from assets/img/country-flags/nz.png rename to assets/dist/img/country-flags/nz.png diff --git a/assets/img/country-flags/om.png b/assets/dist/img/country-flags/om.png similarity index 100% rename from assets/img/country-flags/om.png rename to assets/dist/img/country-flags/om.png diff --git a/assets/img/country-flags/pa.png b/assets/dist/img/country-flags/pa.png similarity index 100% rename from assets/img/country-flags/pa.png rename to assets/dist/img/country-flags/pa.png diff --git a/assets/img/country-flags/pe.png b/assets/dist/img/country-flags/pe.png similarity index 100% rename from assets/img/country-flags/pe.png rename to assets/dist/img/country-flags/pe.png diff --git a/assets/img/country-flags/pf.png b/assets/dist/img/country-flags/pf.png similarity index 100% rename from assets/img/country-flags/pf.png rename to assets/dist/img/country-flags/pf.png diff --git a/assets/img/country-flags/pg.png b/assets/dist/img/country-flags/pg.png similarity index 100% rename from assets/img/country-flags/pg.png rename to assets/dist/img/country-flags/pg.png diff --git a/assets/img/country-flags/ph.png b/assets/dist/img/country-flags/ph.png similarity index 100% rename from assets/img/country-flags/ph.png rename to assets/dist/img/country-flags/ph.png diff --git a/assets/img/country-flags/pk.png b/assets/dist/img/country-flags/pk.png similarity index 100% rename from assets/img/country-flags/pk.png rename to assets/dist/img/country-flags/pk.png diff --git a/assets/img/country-flags/pl.png b/assets/dist/img/country-flags/pl.png similarity index 100% rename from assets/img/country-flags/pl.png rename to assets/dist/img/country-flags/pl.png diff --git a/assets/img/country-flags/pn.png b/assets/dist/img/country-flags/pn.png similarity index 100% rename from assets/img/country-flags/pn.png rename to assets/dist/img/country-flags/pn.png diff --git a/assets/img/country-flags/pr.png b/assets/dist/img/country-flags/pr.png similarity index 100% rename from assets/img/country-flags/pr.png rename to assets/dist/img/country-flags/pr.png diff --git a/assets/img/country-flags/ps.png b/assets/dist/img/country-flags/ps.png similarity index 100% rename from assets/img/country-flags/ps.png rename to assets/dist/img/country-flags/ps.png diff --git a/assets/img/country-flags/pt.png b/assets/dist/img/country-flags/pt.png similarity index 100% rename from assets/img/country-flags/pt.png rename to assets/dist/img/country-flags/pt.png diff --git a/assets/img/country-flags/pw.png b/assets/dist/img/country-flags/pw.png similarity index 100% rename from assets/img/country-flags/pw.png rename to assets/dist/img/country-flags/pw.png diff --git a/assets/img/country-flags/py.png b/assets/dist/img/country-flags/py.png similarity index 100% rename from assets/img/country-flags/py.png rename to assets/dist/img/country-flags/py.png diff --git a/assets/img/country-flags/qa.png b/assets/dist/img/country-flags/qa.png similarity index 100% rename from assets/img/country-flags/qa.png rename to assets/dist/img/country-flags/qa.png diff --git a/assets/img/country-flags/re.png b/assets/dist/img/country-flags/re.png similarity index 100% rename from assets/img/country-flags/re.png rename to assets/dist/img/country-flags/re.png diff --git a/assets/img/country-flags/ro.png b/assets/dist/img/country-flags/ro.png similarity index 100% rename from assets/img/country-flags/ro.png rename to assets/dist/img/country-flags/ro.png diff --git a/assets/img/country-flags/rs.png b/assets/dist/img/country-flags/rs.png similarity index 100% rename from assets/img/country-flags/rs.png rename to assets/dist/img/country-flags/rs.png diff --git a/assets/img/country-flags/ru.png b/assets/dist/img/country-flags/ru.png similarity index 100% rename from assets/img/country-flags/ru.png rename to assets/dist/img/country-flags/ru.png diff --git a/assets/img/country-flags/rw.png b/assets/dist/img/country-flags/rw.png similarity index 100% rename from assets/img/country-flags/rw.png rename to assets/dist/img/country-flags/rw.png diff --git a/assets/img/country-flags/sa.png b/assets/dist/img/country-flags/sa.png similarity index 100% rename from assets/img/country-flags/sa.png rename to assets/dist/img/country-flags/sa.png diff --git a/assets/img/country-flags/sb.png b/assets/dist/img/country-flags/sb.png similarity index 100% rename from assets/img/country-flags/sb.png rename to assets/dist/img/country-flags/sb.png diff --git a/assets/img/country-flags/sc.png b/assets/dist/img/country-flags/sc.png similarity index 100% rename from assets/img/country-flags/sc.png rename to assets/dist/img/country-flags/sc.png diff --git a/assets/img/country-flags/sd.png b/assets/dist/img/country-flags/sd.png similarity index 100% rename from assets/img/country-flags/sd.png rename to assets/dist/img/country-flags/sd.png diff --git a/assets/img/country-flags/se.png b/assets/dist/img/country-flags/se.png similarity index 100% rename from assets/img/country-flags/se.png rename to assets/dist/img/country-flags/se.png diff --git a/assets/img/country-flags/sg.png b/assets/dist/img/country-flags/sg.png similarity index 100% rename from assets/img/country-flags/sg.png rename to assets/dist/img/country-flags/sg.png diff --git a/assets/img/country-flags/sh.png b/assets/dist/img/country-flags/sh.png similarity index 100% rename from assets/img/country-flags/sh.png rename to assets/dist/img/country-flags/sh.png diff --git a/assets/img/country-flags/si.png b/assets/dist/img/country-flags/si.png similarity index 100% rename from assets/img/country-flags/si.png rename to assets/dist/img/country-flags/si.png diff --git a/assets/img/country-flags/sk.png b/assets/dist/img/country-flags/sk.png similarity index 100% rename from assets/img/country-flags/sk.png rename to assets/dist/img/country-flags/sk.png diff --git a/assets/img/country-flags/sl.png b/assets/dist/img/country-flags/sl.png similarity index 100% rename from assets/img/country-flags/sl.png rename to assets/dist/img/country-flags/sl.png diff --git a/assets/img/country-flags/sm.png b/assets/dist/img/country-flags/sm.png similarity index 100% rename from assets/img/country-flags/sm.png rename to assets/dist/img/country-flags/sm.png diff --git a/assets/img/country-flags/sn.png b/assets/dist/img/country-flags/sn.png similarity index 100% rename from assets/img/country-flags/sn.png rename to assets/dist/img/country-flags/sn.png diff --git a/assets/img/country-flags/so.png b/assets/dist/img/country-flags/so.png similarity index 100% rename from assets/img/country-flags/so.png rename to assets/dist/img/country-flags/so.png diff --git a/assets/img/country-flags/sr.png b/assets/dist/img/country-flags/sr.png similarity index 100% rename from assets/img/country-flags/sr.png rename to assets/dist/img/country-flags/sr.png diff --git a/assets/img/country-flags/ss.png b/assets/dist/img/country-flags/ss.png similarity index 100% rename from assets/img/country-flags/ss.png rename to assets/dist/img/country-flags/ss.png diff --git a/assets/img/country-flags/st.png b/assets/dist/img/country-flags/st.png similarity index 100% rename from assets/img/country-flags/st.png rename to assets/dist/img/country-flags/st.png diff --git a/assets/img/country-flags/sv.png b/assets/dist/img/country-flags/sv.png similarity index 100% rename from assets/img/country-flags/sv.png rename to assets/dist/img/country-flags/sv.png diff --git a/assets/img/country-flags/sx.png b/assets/dist/img/country-flags/sx.png similarity index 100% rename from assets/img/country-flags/sx.png rename to assets/dist/img/country-flags/sx.png diff --git a/assets/img/country-flags/sy.png b/assets/dist/img/country-flags/sy.png similarity index 100% rename from assets/img/country-flags/sy.png rename to assets/dist/img/country-flags/sy.png diff --git a/assets/img/country-flags/sz.png b/assets/dist/img/country-flags/sz.png similarity index 100% rename from assets/img/country-flags/sz.png rename to assets/dist/img/country-flags/sz.png diff --git a/assets/img/country-flags/tc.png b/assets/dist/img/country-flags/tc.png similarity index 100% rename from assets/img/country-flags/tc.png rename to assets/dist/img/country-flags/tc.png diff --git a/assets/img/country-flags/td.png b/assets/dist/img/country-flags/td.png similarity index 100% rename from assets/img/country-flags/td.png rename to assets/dist/img/country-flags/td.png diff --git a/assets/img/country-flags/tf.png b/assets/dist/img/country-flags/tf.png similarity index 100% rename from assets/img/country-flags/tf.png rename to assets/dist/img/country-flags/tf.png diff --git a/assets/img/country-flags/tg.png b/assets/dist/img/country-flags/tg.png similarity index 100% rename from assets/img/country-flags/tg.png rename to assets/dist/img/country-flags/tg.png diff --git a/assets/img/country-flags/th.png b/assets/dist/img/country-flags/th.png similarity index 100% rename from assets/img/country-flags/th.png rename to assets/dist/img/country-flags/th.png diff --git a/assets/img/country-flags/tj.png b/assets/dist/img/country-flags/tj.png similarity index 100% rename from assets/img/country-flags/tj.png rename to assets/dist/img/country-flags/tj.png diff --git a/assets/img/country-flags/tk.png b/assets/dist/img/country-flags/tk.png similarity index 100% rename from assets/img/country-flags/tk.png rename to assets/dist/img/country-flags/tk.png diff --git a/assets/img/country-flags/tl.png b/assets/dist/img/country-flags/tl.png similarity index 100% rename from assets/img/country-flags/tl.png rename to assets/dist/img/country-flags/tl.png diff --git a/assets/img/country-flags/tm.png b/assets/dist/img/country-flags/tm.png similarity index 100% rename from assets/img/country-flags/tm.png rename to assets/dist/img/country-flags/tm.png diff --git a/assets/img/country-flags/tn.png b/assets/dist/img/country-flags/tn.png similarity index 100% rename from assets/img/country-flags/tn.png rename to assets/dist/img/country-flags/tn.png diff --git a/assets/img/country-flags/to.png b/assets/dist/img/country-flags/to.png similarity index 100% rename from assets/img/country-flags/to.png rename to assets/dist/img/country-flags/to.png diff --git a/assets/img/country-flags/tr.png b/assets/dist/img/country-flags/tr.png similarity index 100% rename from assets/img/country-flags/tr.png rename to assets/dist/img/country-flags/tr.png diff --git a/assets/img/country-flags/tt.png b/assets/dist/img/country-flags/tt.png similarity index 100% rename from assets/img/country-flags/tt.png rename to assets/dist/img/country-flags/tt.png diff --git a/assets/img/country-flags/tv.png b/assets/dist/img/country-flags/tv.png similarity index 100% rename from assets/img/country-flags/tv.png rename to assets/dist/img/country-flags/tv.png diff --git a/assets/img/country-flags/tw.png b/assets/dist/img/country-flags/tw.png similarity index 100% rename from assets/img/country-flags/tw.png rename to assets/dist/img/country-flags/tw.png diff --git a/assets/img/country-flags/tz.png b/assets/dist/img/country-flags/tz.png similarity index 100% rename from assets/img/country-flags/tz.png rename to assets/dist/img/country-flags/tz.png diff --git a/assets/img/country-flags/ua.png b/assets/dist/img/country-flags/ua.png similarity index 100% rename from assets/img/country-flags/ua.png rename to assets/dist/img/country-flags/ua.png diff --git a/assets/img/country-flags/ug.png b/assets/dist/img/country-flags/ug.png similarity index 100% rename from assets/img/country-flags/ug.png rename to assets/dist/img/country-flags/ug.png diff --git a/assets/img/country-flags/us.png b/assets/dist/img/country-flags/us.png similarity index 100% rename from assets/img/country-flags/us.png rename to assets/dist/img/country-flags/us.png diff --git a/assets/img/country-flags/uy.png b/assets/dist/img/country-flags/uy.png similarity index 100% rename from assets/img/country-flags/uy.png rename to assets/dist/img/country-flags/uy.png diff --git a/assets/img/country-flags/uz.png b/assets/dist/img/country-flags/uz.png similarity index 100% rename from assets/img/country-flags/uz.png rename to assets/dist/img/country-flags/uz.png diff --git a/assets/img/country-flags/va.png b/assets/dist/img/country-flags/va.png similarity index 100% rename from assets/img/country-flags/va.png rename to assets/dist/img/country-flags/va.png diff --git a/assets/img/country-flags/vc.png b/assets/dist/img/country-flags/vc.png similarity index 100% rename from assets/img/country-flags/vc.png rename to assets/dist/img/country-flags/vc.png diff --git a/assets/img/country-flags/ve.png b/assets/dist/img/country-flags/ve.png similarity index 100% rename from assets/img/country-flags/ve.png rename to assets/dist/img/country-flags/ve.png diff --git a/assets/img/country-flags/vg.png b/assets/dist/img/country-flags/vg.png similarity index 100% rename from assets/img/country-flags/vg.png rename to assets/dist/img/country-flags/vg.png diff --git a/assets/img/country-flags/vi.png b/assets/dist/img/country-flags/vi.png similarity index 100% rename from assets/img/country-flags/vi.png rename to assets/dist/img/country-flags/vi.png diff --git a/assets/img/country-flags/vn.png b/assets/dist/img/country-flags/vn.png similarity index 100% rename from assets/img/country-flags/vn.png rename to assets/dist/img/country-flags/vn.png diff --git a/assets/img/country-flags/vu.png b/assets/dist/img/country-flags/vu.png similarity index 100% rename from assets/img/country-flags/vu.png rename to assets/dist/img/country-flags/vu.png diff --git a/assets/img/country-flags/ws.png b/assets/dist/img/country-flags/ws.png similarity index 100% rename from assets/img/country-flags/ws.png rename to assets/dist/img/country-flags/ws.png diff --git a/assets/img/country-flags/ye.png b/assets/dist/img/country-flags/ye.png similarity index 100% rename from assets/img/country-flags/ye.png rename to assets/dist/img/country-flags/ye.png diff --git a/assets/img/country-flags/za.png b/assets/dist/img/country-flags/za.png similarity index 100% rename from assets/img/country-flags/za.png rename to assets/dist/img/country-flags/za.png diff --git a/assets/img/country-flags/zm.png b/assets/dist/img/country-flags/zm.png similarity index 100% rename from assets/img/country-flags/zm.png rename to assets/dist/img/country-flags/zm.png diff --git a/assets/img/country-flags/zw.png b/assets/dist/img/country-flags/zw.png similarity index 100% rename from assets/img/country-flags/zw.png rename to assets/dist/img/country-flags/zw.png diff --git a/assets/img/screenshot.png b/assets/dist/img/screenshot.png similarity index 100% rename from assets/img/screenshot.png rename to assets/dist/img/screenshot.png diff --git a/views/index.html b/assets/dist/index.html similarity index 71% rename from views/index.html rename to assets/dist/index.html index 6748aeb..deb91b5 100644 --- a/views/index.html +++ b/assets/dist/index.html @@ -2,13 +2,13 @@ Ana - open web analytics - +
- + diff --git a/assets/dist/js/script.js b/assets/dist/js/script.js new file mode 100644 index 0000000..8178835 --- /dev/null +++ b/assets/dist/js/script.js @@ -0,0 +1,28466 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i 0 ? 'positive' : 'negative' }, + percentage, + '%' + ); + } + }, { + key: 'render', + value: function render() { + var loadingOverlay = this.state.loading ? (0, _preact.h)( + 'div', + { 'class': 'loading-overlay' }, + (0, _preact.h)('div', null) + ) : ''; + return (0, _preact.h)( + 'div', + { 'class': 'block center-text' }, + loadingOverlay, + (0, _preact.h)( + 'h4', + { 'class': '' }, + this.props.title + ), + (0, _preact.h)( + 'div', + { 'class': 'big tiny-margin' }, + numbers.formatWithComma(this.state.count), + ' ', + this.renderPercentage() + ) + ); + } + }]); + + return CountWidget; +}(_preact.Component); + +exports.default = CountWidget; + +},{"../lib/client.js":12,"../lib/numbers.js":13,"preact":61}],2:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var availablePeriods = [{ + id: 7, + label: 'Last 7 days' +}, { + id: 30, + label: 'Last 30 days' +}, { + id: 90, + label: 'Last quarter' +}, { + id: 360, + label: 'Last year' +}]; + +var DatePicker = function (_Component) { + _inherits(DatePicker, _Component); + + function DatePicker(props) { + _classCallCheck(this, DatePicker); + + var _this = _possibleConstructorReturn(this, (DatePicker.__proto__ || Object.getPrototypeOf(DatePicker)).call(this, props)); + + _this.state = { + period: _this.props.period + }; + + _this.setPeriod = _this.setPeriod.bind(_this); + return _this; + } + + _createClass(DatePicker, [{ + key: 'setPeriod', + value: function setPeriod(e) { + var nextState = { period: parseInt(e.target.value) }; + if (this.state.period != nextState.period) { + this.setState(nextState); + this.props.onChoose(this.state.period); + } + } + }, { + key: 'render', + value: function render() { + var _this2 = this; + + var buttons = availablePeriods.map(function (p) { + var className = p.id == _this2.state.period ? 'active' : ''; + return (0, _preact.h)( + 'button', + { value: p.id, 'class': className, onClick: _this2.setPeriod }, + p.label + ); + }); + + return (0, _preact.h)( + 'div', + { 'class': 'small-margin' }, + buttons + ); + } + }]); + + return DatePicker; +}(_preact.Component); + +exports.default = DatePicker; + +},{"preact":61}],3:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _client = require('../lib/client.js'); + +var _client2 = _interopRequireDefault(_client); + +var _numbers = require('../lib/numbers.js'); + +var numbers = _interopRequireWildcard(_numbers); + +var _d = require('d3'); + +var d3 = _interopRequireWildcard(_d); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +d3.tip = require('d3-tip'); + +var dayInSeconds = 60 * 60 * 24; + +function Chart(element, showPrimary, showSecondary) { + var padt = 10, + padb = 20, + padr = 40, + padl = 40, + h = 300, + w = element.parentNode.clientWidth - padl - padr, + x = d3.scaleBand().range([0, w]).padding(0.2).round(true), + y = d3.scaleLinear().range([h, 0]), + yAxis = d3.axisLeft().scale(y).tickSize(-w + padl + padr), + xAxis = d3.axisBottom().scale(x), + primaryData = [], + secondaryData = []; + + var pageviewTip = d3.tip().attr('class', 'd3-tip').html(function (d) { + return '
' + d.Label + '
' + numbers.formatWithComma(d.Value) + '' + ' pageviews'; + }).offset([-12, 0]); + + var visitorTip = d3.tip().attr('class', 'd3-tip').html(function (d) { + return '
' + d.Label + '
' + numbers.formatWithComma(d.Value) + '' + ' visitors'; + }).offset([-12, 0]); + + var graph = d3.select('#graph'); + var vis = graph.append('svg').attr('width', w + padl + padr).attr('height', h + padt + padb).append('g').attr('transform', 'translate(' + padl + ',' + padt + ')'); + + vis.call(pageviewTip); + vis.call(visitorTip); + + function setData(one, two) { + primaryData = one; + secondaryData = two; + } + + function toggleBars(one, two) { + showPrimary = one; + showSecondary = two; + } + + function draw() { + var max = d3.max(showPrimary ? primaryData : secondaryData, function (d) { + return d.Value; + }); + var ticks = primaryData.length; + var xTick = Math.round(ticks / 7); + + x.domain(primaryData.map(function (d) { + return d.Label; + })); + y.domain([0, max * 1.1]); + + // clear all previous data + vis.selectAll('*').remove(); + + // axes + vis.append("g").attr("class", "y axis").call(yAxis); + + vis.append("g").attr("class", "x axis").attr('transform', 'translate(0,' + h + ')').call(xAxis).selectAll('g').style('display', function (d, i) { + return i % xTick != 0 ? 'none' : 'block'; + }); + + // bars + if (showPrimary) { + var bars = vis.selectAll('g.primary-bar').data(primaryData).enter().append('g').attr('class', 'primary-bar').attr('transform', function (d, i) { + return "translate(" + x(d.Label) + ", 0)"; + }); + + bars.append('rect').attr('width', x.bandwidth()).attr('height', function (d) { + return h - y(d.Value); + }).attr('y', function (d) { + return y(d.Value); + }).on('mouseover', pageviewTip.show).on('mouseout', pageviewTip.hide); + } + + if (showSecondary) { + var visitorBars = vis.selectAll('g.sub-bar').data(secondaryData).enter().append('g').attr('class', 'sub-bar').attr('transform', function (d, i) { + return "translate(" + (x(d.Label) + x.bandwidth() * 0.16667) + ", 0)"; + }); + + visitorBars.append('rect').attr('width', x.bandwidth() * 0.66).attr('height', function (d) { + return h - y(d.Value); + }).attr('y', function (d) { + return y(d.Value); + }).on('mouseover', visitorTip.show).on('mouseout', visitorTip.hide); + } + } + + return { + 'draw': draw, + 'setData': setData, + 'toggleBars': toggleBars + }; +} + +var Graph = function (_Component) { + _inherits(Graph, _Component); + + function Graph(props) { + _classCallCheck(this, Graph); + + var _this = _possibleConstructorReturn(this, (Graph.__proto__ || Object.getPrototypeOf(Graph)).call(this, props)); + + _this.fetchData = _this.fetchData.bind(_this); + _this.refreshChart = _this.refreshChart.bind(_this); + _this.data = { + visitors: null, + pageviews: null + }; + return _this; + } + + _createClass(Graph, [{ + key: 'componentDidMount', + value: function componentDidMount() { + this.chart = new Chart(document.getElementById('graph'), this.props.showPageviews, this.props.showVisitors); + this.fetchData(this.props.period); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(newProps) { + if (this.props.period != newProps.period) { + this.fetchData(newProps.period); + } + + this.chart.toggleBars(newProps.showPageviews, newProps.showVisitors); + this.chart.draw(); + } + }, { + key: 'shouldComponentUpdate', + value: function shouldComponentUpdate() { + return false; + } + }, { + key: 'refreshChart', + value: function refreshChart() { + + if (this.data.visitors && this.data.pageviews) { + this.loadingIndicator.style.display = 'none'; + this.chart.setData(this.data.pageviews, this.data.visitors); + this.chart.draw(); + } + } + }, { + key: 'fetchData', + value: function fetchData(period) { + var _this2 = this; + + var before = Math.round(+new Date() / 1000); + var after = before - period * dayInSeconds; + var group = period > 90 ? 'month' : 'day'; + this.loadingIndicator.style.display = ''; + + _client2.default.request('pageviews/count/group/' + group + '?before=' + before + '&after=' + after).then(function (d) { + _this2.data.pageviews = d; + window.requestAnimationFrame(_this2.refreshChart); + }); + + _client2.default.request('visitors/count/group/' + group + '?before=' + before + '&after=' + after).then(function (d) { + _this2.data.visitors = d; + window.requestAnimationFrame(_this2.refreshChart); + }); + } + }, { + key: 'render', + value: function render() { + var _this3 = this; + + return (0, _preact.h)( + 'div', + null, + (0, _preact.h)( + 'div', + { 'class': 'loading-overlay', ref: function ref(el) { + _this3.loadingIndicator = el; + } }, + (0, _preact.h)('div', null) + ), + (0, _preact.h)('div', { id: 'graph' }) + ); + } + }]); + + return Graph; +}(_preact.Component); + +exports.default = Graph; + +},{"../lib/client.js":12,"../lib/numbers.js":13,"d3":54,"d3-tip":50,"preact":61}],4:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _Graph = require('./Graph.js'); + +var _Graph2 = _interopRequireDefault(_Graph); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var GraphWidget = function (_Component) { + _inherits(GraphWidget, _Component); + + function GraphWidget(props) { + _classCallCheck(this, GraphWidget); + + var _this = _possibleConstructorReturn(this, (GraphWidget.__proto__ || Object.getPrototypeOf(GraphWidget)).call(this, props)); + + _this.state = { + showPageviews: true, + showVisitors: true + }; + return _this; + } + + _createClass(GraphWidget, [{ + key: 'render', + value: function render() { + var _this2 = this; + + return (0, _preact.h)( + 'div', + { 'class': 'block' }, + (0, _preact.h)( + 'div', + { 'class': 'pull-right' }, + (0, _preact.h)( + 'label', + { 'class': 'inline small-margin-right' }, + (0, _preact.h)('input', { type: 'checkbox', checked: this.state.showPageviews, onchange: function onchange(e) { + return _this2.setState({ showPageviews: e.target.checked }); + } }), + ' Pageviews' + ), + (0, _preact.h)( + 'label', + { 'class': 'inline' }, + (0, _preact.h)('input', { type: 'checkbox', checked: this.state.showVisitors, onchange: function onchange(e) { + return _this2.setState({ showVisitors: e.target.checked }); + } }), + ' Visitors' + ) + ), + (0, _preact.h)(_Graph2.default, { period: this.props.period, showPageviews: this.state.showPageviews, showVisitors: this.state.showVisitors }) + ); + } + }]); + + return GraphWidget; +}(_preact.Component); + +exports.default = GraphWidget; + +},{"./Graph.js":3,"preact":61}],5:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _LogoutButton = require('../components/LogoutButton.js'); + +var _LogoutButton2 = _interopRequireDefault(_LogoutButton); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var HeaderBar = function (_Component) { + _inherits(HeaderBar, _Component); + + function HeaderBar() { + _classCallCheck(this, HeaderBar); + + return _possibleConstructorReturn(this, (HeaderBar.__proto__ || Object.getPrototypeOf(HeaderBar)).apply(this, arguments)); + } + + _createClass(HeaderBar, [{ + key: 'render', + value: function render() { + var rightContent = this.props.showLogout ? (0, _preact.h)(_LogoutButton2.default, { onSuccess: this.props.onLogout }) : ''; + + return (0, _preact.h)( + 'header', + { 'class': 'header-bar cf' }, + (0, _preact.h)( + 'div', + { 'class': 'container' }, + (0, _preact.h)( + 'h1', + { 'class': 'pull-left title' }, + 'Ana ', + (0, _preact.h)( + 'small', + { 'class': 'subtitle' }, + 'open web analytics' + ) + ), + (0, _preact.h)( + 'div', + { 'class': 'pull-right' }, + rightContent + ) + ) + ); + } + }]); + + return HeaderBar; +}(_preact.Component); + +exports.default = HeaderBar; + +},{"../components/LogoutButton.js":7,"preact":61}],6:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _client = require('../lib/client.js'); + +var _client2 = _interopRequireDefault(_client); + +var _Notification = require('../components/Notification.js'); + +var _Notification2 = _interopRequireDefault(_Notification); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var LoginForm = function (_Component) { + _inherits(LoginForm, _Component); + + function LoginForm(props) { + _classCallCheck(this, LoginForm); + + var _this = _possibleConstructorReturn(this, (LoginForm.__proto__ || Object.getPrototypeOf(LoginForm)).call(this, props)); + + _this.handleSubmit = _this.handleSubmit.bind(_this); + _this.state = { + email: '', + password: '', + message: '' + }; + return _this; + } + + _createClass(LoginForm, [{ + key: 'handleSubmit', + value: function handleSubmit(e) { + var _this2 = this; + + e.preventDefault(); + + _client2.default.request('session', { + method: "POST", + data: { + email: this.state.email, + password: this.state.password + } + }).then(function (r) { + _this2.props.onSuccess(); + }).catch(function (e) { + _this2.setState({ + message: e.message, + password: '' + }); + }); + } + }, { + key: 'render', + value: function render() { + return (0, _preact.h)( + 'div', + { 'class': 'block' }, + (0, _preact.h)( + 'h2', + null, + 'Login' + ), + (0, _preact.h)( + 'p', + null, + 'Please enter your credentials to access your Ana dashboard.' + ), + (0, _preact.h)( + 'form', + { method: 'POST', onSubmit: this.handleSubmit }, + (0, _preact.h)( + 'div', + { 'class': 'small-margin' }, + (0, _preact.h)( + 'label', + null, + 'Email address' + ), + (0, _preact.h)('input', { type: 'email', name: 'email', placeholder: 'Email address', value: this.state.email, onChange: this.linkState('email'), required: 'required' }) + ), + (0, _preact.h)( + 'div', + { 'class': 'small-margin' }, + (0, _preact.h)( + 'label', + null, + 'Password' + ), + (0, _preact.h)('input', { type: 'password', name: 'password', placeholder: '**********', value: this.state.password, onChange: this.linkState('password'), required: 'required' }) + ), + (0, _preact.h)( + 'div', + { 'class': 'small-margin' }, + (0, _preact.h)('input', { type: 'submit', value: 'Sign in' }) + ) + ), + (0, _preact.h)(_Notification2.default, { message: this.state.message, kind: '' }) + ); + } + }]); + + return LoginForm; +}(_preact.Component); + +exports.default = LoginForm; + +},{"../components/Notification.js":8,"../lib/client.js":12,"preact":61}],7:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _client = require('../lib/client.js'); + +var _client2 = _interopRequireDefault(_client); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var LogoutButton = function (_Component) { + _inherits(LogoutButton, _Component); + + function LogoutButton(props) { + _classCallCheck(this, LogoutButton); + + var _this = _possibleConstructorReturn(this, (LogoutButton.__proto__ || Object.getPrototypeOf(LogoutButton)).call(this, props)); + + _this.handleSubmit = _this.handleSubmit.bind(_this); + return _this; + } + + _createClass(LogoutButton, [{ + key: 'handleSubmit', + value: function handleSubmit(e) { + var _this2 = this; + + e.preventDefault(); + + _client2.default.request('session', { + method: "DELETE" + }).then(function (r) { + _this2.props.onSuccess(); + }); + } + }, { + key: 'render', + value: function render() { + return (0, _preact.h)( + 'a', + { href: '#', onClick: this.handleSubmit }, + 'Sign out' + ); + } + }]); + + return LogoutButton; +}(_preact.Component); + +exports.default = LogoutButton; + +},{"../lib/client.js":12,"preact":61}],8:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Notification = function (_Component) { + _inherits(Notification, _Component); + + function Notification(props) { + _classCallCheck(this, Notification); + + var _this = _possibleConstructorReturn(this, (Notification.__proto__ || Object.getPrototypeOf(Notification)).call(this, props)); + + _this.state = { + message: props.message, + kind: props.kind || 'error' + }; + _this.timeout = 0; + return _this; + } + + _createClass(Notification, [{ + key: 'clearMessage', + value: function clearMessage() { + this.setState({ message: '' }); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(newProps) { + if (newProps.message != this.state.message) { + this.setState({ message: newProps.message, kind: newProps.kind || 'error' }); + window.clearTimeout(this.timeout); + this.timeout = window.setTimeout(this.clearMessage.bind(this), 5000); + } + } + }, { + key: 'render', + value: function render() { + if (this.state.message === '') { + return ''; + } + + return (0, _preact.h)( + 'div', + { 'class': 'notification' }, + (0, _preact.h)( + 'div', + { 'class': 'notification-' + this.state.kind }, + this.state.message + ) + ); + } + }]); + + return Notification; +}(_preact.Component); + +exports.default = Notification; + +},{"preact":61}],9:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _numbers = require('../lib/numbers.js'); + +var numbers = _interopRequireWildcard(_numbers); + +var _client = require('../lib/client.js'); + +var _client2 = _interopRequireDefault(_client); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var dayInSeconds = 60 * 60 * 24; + +var Pageviews = function (_Component) { + _inherits(Pageviews, _Component); + + function Pageviews(props) { + _classCallCheck(this, Pageviews); + + var _this = _possibleConstructorReturn(this, (Pageviews.__proto__ || Object.getPrototypeOf(Pageviews)).call(this, props)); + + _this.state = { + records: [], + loading: false + }; + _this.fetchRecords = _this.fetchRecords.bind(_this); + return _this; + } + + _createClass(Pageviews, [{ + key: 'componentDidMount', + value: function componentDidMount() { + this.fetchRecords(this.props.period); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(newProps) { + if (this.props.period != newProps.period) { + this.fetchRecords(newProps.period); + } + } + }, { + key: 'fetchRecords', + value: function fetchRecords(period) { + var _this2 = this; + + var before = Math.round(+new Date() / 1000); + var after = before - period * dayInSeconds; + this.setState({ loading: true }); + + _client2.default.request('pageviews?before=' + before + '&after=' + after).then(function (d) { + _this2.setState({ loading: false, records: d }); + }).catch(function (e) { + console.log(e); + }); + } + }, { + key: 'render', + value: function render() { + var loadingOverlay = this.state.loading ? (0, _preact.h)( + 'div', + { 'class': 'loading-overlay' }, + (0, _preact.h)('div', null) + ) : ''; + var tableRows = this.state.records.map(function (p, i) { + return (0, _preact.h)( + 'tr', + null, + (0, _preact.h)( + 'td', + { 'class': 'muted' }, + i + 1 + ), + (0, _preact.h)( + 'td', + null, + (0, _preact.h)( + 'a', + { href: "//" + p.Hostname + p.Path }, + p.Path.substring(0, 50), + p.Path.length > 50 ? '..' : '' + ) + ), + (0, _preact.h)( + 'td', + null, + numbers.formatWithComma(p.Count) + ), + (0, _preact.h)( + 'td', + null, + numbers.formatWithComma(p.CountUnique) + ) + ); + }); + + return (0, _preact.h)( + 'div', + { 'class': 'block' }, + loadingOverlay, + (0, _preact.h)( + 'h3', + null, + 'Pageviews' + ), + (0, _preact.h)( + 'table', + { 'class': 'table pageviews' }, + (0, _preact.h)( + 'thead', + null, + (0, _preact.h)( + 'tr', + null, + (0, _preact.h)( + 'th', + null, + '#' + ), + (0, _preact.h)( + 'th', + null, + 'URL' + ), + (0, _preact.h)( + 'th', + null, + 'Pageviews' + ), + (0, _preact.h)( + 'th', + null, + 'Unique' + ) + ) + ), + (0, _preact.h)( + 'tbody', + null, + tableRows + ) + ) + ); + } + }]); + + return Pageviews; +}(_preact.Component); + +exports.default = Pageviews; + +},{"../lib/client.js":12,"../lib/numbers.js":13,"preact":61}],10:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _client = require('../lib/client.js'); + +var _client2 = _interopRequireDefault(_client); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Realtime = function (_Component) { + _inherits(Realtime, _Component); + + function Realtime(props) { + _classCallCheck(this, Realtime); + + var _this = _possibleConstructorReturn(this, (Realtime.__proto__ || Object.getPrototypeOf(Realtime)).call(this, props)); + + _this.state = { + count: 0 + }; + _this.fetchData = _this.fetchData.bind(_this); + _this.fetchData(); + window.setInterval(_this.fetchData, 15000); + return _this; + } + + _createClass(Realtime, [{ + key: 'fetchData', + value: function fetchData() { + var _this2 = this; + + _client2.default.request('visitors/count/realtime').then(function (d) { + _this2.setState({ count: d }); + }); + } + }, { + key: 'render', + value: function render() { + var visitors = this.state.count == 1 ? 'visitor' : 'visitors'; + return (0, _preact.h)( + 'div', + { 'class': 'block block-float' }, + (0, _preact.h)( + 'span', + { 'class': 'count' }, + this.state.count + ), + ' ', + (0, _preact.h)( + 'span', + null, + visitors, + ' on the site right now.' + ) + ); + } + }]); + + return Realtime; +}(_preact.Component); + +exports.default = Realtime; + +},{"../lib/client.js":12,"preact":61}],11:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _numbers = require('../lib/numbers.js'); + +var numbers = _interopRequireWildcard(_numbers); + +var _client = require('../lib/client.js'); + +var _client2 = _interopRequireDefault(_client); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var dayInSeconds = 60 * 60 * 24; + +var Table = function (_Component) { + _inherits(Table, _Component); + + function Table(props) { + _classCallCheck(this, Table); + + var _this = _possibleConstructorReturn(this, (Table.__proto__ || Object.getPrototypeOf(Table)).call(this, props)); + + _this.state = { + records: [], + limit: 5, + loading: true + }; + + _this.tableHeaders = props.headers.map(function (heading) { + return (0, _preact.h)( + 'th', + null, + heading + ); + }); + _this.fetchRecords = _this.fetchRecords.bind(_this); + _this.handleLimitChoice = _this.handleLimitChoice.bind(_this); + return _this; + } + + _createClass(Table, [{ + key: 'componentDidMount', + value: function componentDidMount() { + this.fetchRecords(this.props.period, this.state.limit); + } + }, { + key: 'labelCell', + value: function labelCell(p) { + if (this.props.labelCell) { + return this.props.labelCell(p); + } + + return (0, _preact.h)( + 'td', + null, + p.Label.substring(0, 15) + ); + } + }, { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(newProps) { + if (this.props.period != newProps.period) { + this.fetchRecords(newProps.period, this.state.limit); + } + } + }, { + key: 'handleLimitChoice', + value: function handleLimitChoice(e) { + this.setState({ limit: parseInt(e.target.value) }); + this.fetchRecords(this.props.period, this.state.limit); + } + }, { + key: 'fetchRecords', + value: function fetchRecords(period, limit) { + var _this2 = this; + + this.setState({ loading: true }); + var before = Math.round(+new Date() / 1000); + var after = before - period * dayInSeconds; + + _client2.default.request(this.props.endpoint + '?before=' + before + '&after=' + after + '&limit=' + limit).then(function (d) { + _this2.setState({ loading: false, records: d }); + }).catch(function (e) { + console.log(e); + }); + } + }, { + key: 'render', + value: function render() { + var _this3 = this; + + var tableRows = this.state.records.length > 0 ? this.state.records.map(function (p, i) { + return (0, _preact.h)( + 'tr', + null, + (0, _preact.h)( + 'td', + { 'class': 'muted' }, + i + 1 + ), + _this3.labelCell(p), + (0, _preact.h)( + 'td', + null, + numbers.formatWithComma(p.Value) + ), + (0, _preact.h)( + 'td', + null, + Math.round(p.PercentageValue), + '%' + ) + ); + }) : (0, _preact.h)( + 'tr', + null, + (0, _preact.h)( + 'td', + { colspan: '4', 'class': 'italic' }, + 'Nothing here..' + ) + ); + + var loadingOverlay = this.state.loading ? (0, _preact.h)( + 'div', + { 'class': 'loading-overlay' }, + (0, _preact.h)('div', null) + ) : ''; + + return (0, _preact.h)( + 'div', + { 'class': 'block' }, + loadingOverlay, + (0, _preact.h)( + 'div', + { 'class': 'clearfix' }, + (0, _preact.h)( + 'h3', + { 'class': 'pull-left' }, + this.props.title + ), + (0, _preact.h)( + 'div', + { 'class': 'pull-right' }, + (0, _preact.h)( + 'select', + { onchange: this.handleLimitChoice }, + (0, _preact.h)( + 'option', + null, + '5' + ), + (0, _preact.h)( + 'option', + null, + '20' + ), + (0, _preact.h)( + 'option', + null, + '100' + ) + ) + ) + ), + (0, _preact.h)( + 'table', + null, + (0, _preact.h)( + 'thead', + null, + (0, _preact.h)( + 'tr', + null, + this.tableHeaders + ) + ), + (0, _preact.h)( + 'tbody', + null, + tableRows + ) + ) + ); + } + }]); + + return Table; +}(_preact.Component); + +exports.default = Table; + +},{"../lib/client.js":12,"../lib/numbers.js":13,"preact":61}],12:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +var Client = {}; +Client.request = function (resource, args) { + args = args || {}; + args.credentials = 'same-origin'; + args.headers = args.headers || {}; + args.headers['Accept'] = 'application/json'; + + if (args.method && args.method === 'POST') { + args.headers['Content-Type'] = 'application/json'; + + if (args.data) { + if (typeof args.data !== "string") { + args.data = JSON.stringify(args.data); + } + args.body = args.data; + delete args.data; + } + } + + return fetch('/api/' + resource, args).then(parseJSON).then(checkData); +}; + +function parseJSON(r) { + return r.json(); +} + +function checkData(d) { + if (d.Error) { + throw new Error(d.Error); + } + + return d.Data; +} + +exports.default = Client; + +},{}],13:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +function formatWithComma(nStr) { + nStr += ''; + + if (nStr.length < 4) { + return nStr; + } + + var x = nStr.split('.'); + var x1 = x[0]; + var x2 = x.length > 1 ? '.' + x[1] : ''; + var rgx = /(\d+)(\d{3})/; + while (rgx.test(x1)) { + x1 = x1.replace(rgx, '$1' + ',' + '$2'); + } + return x1 + x2; +} + +exports.formatWithComma = formatWithComma; + +},{}],14:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _Pageviews = require('../components/Pageviews.js'); + +var _Pageviews2 = _interopRequireDefault(_Pageviews); + +var _Realtime = require('../components/Realtime.js'); + +var _Realtime2 = _interopRequireDefault(_Realtime); + +var _GraphWidget = require('../components/GraphWidget.js'); + +var _GraphWidget2 = _interopRequireDefault(_GraphWidget); + +var _DatePicker = require('../components/DatePicker.js'); + +var _DatePicker2 = _interopRequireDefault(_DatePicker); + +var _Table = require('../components/Table.js'); + +var _Table2 = _interopRequireDefault(_Table); + +var _HeaderBar = require('../components/HeaderBar.js'); + +var _HeaderBar2 = _interopRequireDefault(_HeaderBar); + +var _CountWidget = require('../components/CountWidget.js'); + +var _CountWidget2 = _interopRequireDefault(_CountWidget); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +function removeImgElement(e) { + e.target.parentNode.removeChild(e.target); +} + +function formatCountryLabel(p) { + var src = "/static/img/country-flags/" + p.Label.toLowerCase() + ".png"; + + return (0, _preact.h)( + 'td', + null, + p.Label, + (0, _preact.h)('img', { height: '12', src: src, 'class': 'pull-right', onError: removeImgElement }) + ); +} + +var Dashboard = function (_Component) { + _inherits(Dashboard, _Component); + + function Dashboard(props) { + _classCallCheck(this, Dashboard); + + var _this = _possibleConstructorReturn(this, (Dashboard.__proto__ || Object.getPrototypeOf(Dashboard)).call(this, props)); + + _this.state = { + period: parseInt(window.location.hash.substring(2)) || 7 + }; + + _this.onPeriodChoose = _this.onPeriodChoose.bind(_this); + return _this; + } + + _createClass(Dashboard, [{ + key: 'onPeriodChoose', + value: function onPeriodChoose(p) { + this.setState({ period: p }); + window.history.replaceState(this.state, null, '#!' + p); + } + }, { + key: 'render', + value: function render() { + return (0, _preact.h)( + 'div', + null, + (0, _preact.h)(_HeaderBar2.default, { showLogout: true, onLogout: this.props.onLogout }), + (0, _preact.h)( + 'div', + { 'class': 'container' }, + (0, _preact.h)(_Realtime2.default, null), + (0, _preact.h)( + 'div', + { 'class': 'clear' }, + (0, _preact.h)(_DatePicker2.default, { period: this.state.period, onChoose: this.onPeriodChoose }) + ), + (0, _preact.h)( + 'div', + { 'class': 'row' }, + (0, _preact.h)( + 'div', + { 'class': 'col-2' }, + (0, _preact.h)(_CountWidget2.default, { title: 'Visitors', endpoint: 'visitors', period: this.state.period }) + ), + (0, _preact.h)( + 'div', + { 'class': 'col-2' }, + (0, _preact.h)(_CountWidget2.default, { title: 'Pageviews', endpoint: 'pageviews', period: this.state.period }) + ) + ), + (0, _preact.h)(_GraphWidget2.default, { period: this.state.period }), + (0, _preact.h)( + 'div', + { 'class': 'row' }, + (0, _preact.h)( + 'div', + { 'class': 'col-4' }, + (0, _preact.h)(_Pageviews2.default, { period: this.state.period }) + ), + (0, _preact.h)( + 'div', + { 'class': 'col-2' }, + (0, _preact.h)(_Table2.default, { period: this.state.period, endpoint: 'languages', title: 'Languages', headers: ["#", "Language", "Count", "%"] }) + ) + ), + (0, _preact.h)( + 'div', + { 'class': 'row' }, + (0, _preact.h)( + 'div', + { 'class': 'col-2' }, + (0, _preact.h)(_Table2.default, { period: this.state.period, endpoint: 'screen-resolutions', title: 'Screen Resolutions', headers: ["#", "Resolution", "Count", "%"] }) + ), + (0, _preact.h)( + 'div', + { 'class': 'col-2' }, + (0, _preact.h)(_Table2.default, { period: this.state.period, endpoint: 'referrers', title: 'Referrers', headers: ["#", "URL", "Count", "%"], labelCell: function labelCell(p) { + return (0, _preact.h)( + 'td', + null, + (0, _preact.h)( + 'a', + { href: "//" + p.Label }, + p.Label.substring(0, 15).replace('https://', '').replace('http://', '') + ) + ); + } }) + ), + (0, _preact.h)( + 'div', + { 'class': 'col-2' }, + (0, _preact.h)(_Table2.default, { period: this.state.period, endpoint: 'browsers', title: 'Browsers', headers: ["#", "Browser", "Count", "%"], onAuthError: this.props.onLogout }) + ) + ) + ) + ); + } + }]); + + return Dashboard; +}(_preact.Component); + +exports.default = Dashboard; + +},{"../components/CountWidget.js":1,"../components/DatePicker.js":2,"../components/GraphWidget.js":4,"../components/HeaderBar.js":5,"../components/Pageviews.js":9,"../components/Realtime.js":10,"../components/Table.js":11,"preact":61}],15:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _LoginForm = require('../components/LoginForm.js'); + +var _LoginForm2 = _interopRequireDefault(_LoginForm); + +var _HeaderBar = require('../components/HeaderBar.js'); + +var _HeaderBar2 = _interopRequireDefault(_HeaderBar); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var Login = function (_Component) { + _inherits(Login, _Component); + + function Login() { + _classCallCheck(this, Login); + + return _possibleConstructorReturn(this, (Login.__proto__ || Object.getPrototypeOf(Login)).apply(this, arguments)); + } + + _createClass(Login, [{ + key: 'render', + value: function render() { + return (0, _preact.h)( + 'div', + null, + (0, _preact.h)(_HeaderBar2.default, { showLogout: false }), + (0, _preact.h)( + 'div', + { 'class': 'container' }, + (0, _preact.h)(_LoginForm2.default, { onSuccess: this.props.onLogin }) + ) + ); + } + }]); + + return Login; +}(_preact.Component); + +exports.default = Login; + +},{"../components/HeaderBar.js":5,"../components/LoginForm.js":6,"preact":61}],16:[function(require,module,exports){ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _preact = require('preact'); + +var _login = require('./pages/login.js'); + +var _login2 = _interopRequireDefault(_login); + +var _dashboard = require('./pages/dashboard.js'); + +var _dashboard2 = _interopRequireDefault(_dashboard); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var App = function (_Component) { + _inherits(App, _Component); + + function App(props) { + _classCallCheck(this, App); + + var _this = _possibleConstructorReturn(this, (App.__proto__ || Object.getPrototypeOf(App)).call(this, props)); + + _this.state = { + authenticated: document.cookie.indexOf('auth') > -1 + }; + return _this; + } + + _createClass(App, [{ + key: 'render', + value: function render() { + var _this2 = this; + + // logged-in + if (this.state.authenticated) { + return (0, _preact.h)(_dashboard2.default, { onLogout: function onLogout() { + return _this2.setState({ authenticated: false }); + } }); + } + + // logged-out + return (0, _preact.h)(_login2.default, { onLogin: function onLogin() { + return _this2.setState({ authenticated: true }); + } }); + } + }]); + + return App; +}(_preact.Component); + +(0, _preact.render)((0, _preact.h)(App, null), document.getElementById('root')); + +},{"./pages/dashboard.js":14,"./pages/login.js":15,"preact":61}],17:[function(require,module,exports){ +'use strict' + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + for (var i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + +},{}],18:[function(require,module,exports){ + +},{}],19:[function(require,module,exports){ +arguments[4][18][0].apply(exports,arguments) +},{"dup":18}],20:[function(require,module,exports){ +(function (global){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') +var isArray = require('isarray') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined + ? global.TYPED_ARRAY_SUPPORT + : typedArraySupport() + +/* + * Export kMaxLength after typed array support is determined. + */ +exports.kMaxLength = kMaxLength() + +function typedArraySupport () { + try { + var arr = new Uint8Array(1) + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} + return arr.foo() === 42 && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +} + +function kMaxLength () { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff +} + +function createBuffer (that, length) { + if (kMaxLength() < length) { + throw new RangeError('Invalid typed array length') + } + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = new Uint8Array(length) + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + if (that === null) { + that = new Buffer(length) + } + that.length = length + } + + return that +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { + return new Buffer(arg, encodingOrOffset, length) + } + + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new Error( + 'If encoding is specified then the first argument must be a string' + ) + } + return allocUnsafe(this, arg) + } + return from(this, arg, encodingOrOffset, length) +} + +Buffer.poolSize = 8192 // not used by this implementation + +// TODO: Legacy, not needed anymore. Remove in next major version. +Buffer._augment = function (arr) { + arr.__proto__ = Buffer.prototype + return arr +} + +function from (that, value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number') + } + + if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { + return fromArrayBuffer(that, value, encodingOrOffset, length) + } + + if (typeof value === 'string') { + return fromString(that, value, encodingOrOffset) + } + + return fromObject(that, value) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(null, value, encodingOrOffset, length) +} + +if (Buffer.TYPED_ARRAY_SUPPORT) { + Buffer.prototype.__proto__ = Uint8Array.prototype + Buffer.__proto__ = Uint8Array + if (typeof Symbol !== 'undefined' && Symbol.species && + Buffer[Symbol.species] === Buffer) { + // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true + }) + } +} + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be a number') + } else if (size < 0) { + throw new RangeError('"size" argument must not be negative') + } +} + +function alloc (that, size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(that, size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(that, size).fill(fill, encoding) + : createBuffer(that, size).fill(fill) + } + return createBuffer(that, size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(null, size, fill, encoding) +} + +function allocUnsafe (that, size) { + assertSize(size) + that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < size; ++i) { + that[i] = 0 + } + } + return that +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(null, size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(null, size) +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('"encoding" must be a valid string encoding') + } + + var length = byteLength(string, encoding) | 0 + that = createBuffer(that, length) + + var actual = that.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + that = that.slice(0, actual) + } + + return that +} + +function fromArrayLike (that, array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + that = createBuffer(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function fromArrayBuffer (that, array, byteOffset, length) { + array.byteLength // this throws if `array` is not a valid ArrayBuffer + + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('\'offset\' is out of bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('\'length\' is out of bounds') + } + + if (byteOffset === undefined && length === undefined) { + array = new Uint8Array(array) + } else if (length === undefined) { + array = new Uint8Array(array, byteOffset) + } else { + array = new Uint8Array(array, byteOffset, length) + } + + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = array + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + that = fromArrayLike(that, array) + } + return that +} + +function fromObject (that, obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + that = createBuffer(that, len) + + if (that.length === 0) { + return that + } + + obj.copy(that, 0, 0, len) + return that + } + + if (obj) { + if ((typeof ArrayBuffer !== 'undefined' && + obj.buffer instanceof ArrayBuffer) || 'length' in obj) { + if (typeof obj.length !== 'number' || isnan(obj.length)) { + return createBuffer(that, 0) + } + return fromArrayLike(that, obj) + } + + if (obj.type === 'Buffer' && isArray(obj.data)) { + return fromArrayLike(that, obj.data) + } + } + + throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') +} + +function checked (length) { + // Note: cannot use `length < kMaxLength()` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && + (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + string = '' + string + } + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + case undefined: + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect +// Buffer instances. +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length | 0 + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (!Buffer.isBuffer(target)) { + throw new TypeError('Argument must be a Buffer') + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (isNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (Buffer.TYPED_ARRAY_SUPPORT && + typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0 + if (isFinite(length)) { + length = length | 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf + if (Buffer.TYPED_ARRAY_SUPPORT) { + newBuf = this.subarray(start, end) + newBuf.__proto__ = Buffer.prototype + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; ++i) { + newBuf[i] = this[i + start] + } + } + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = (value & 0xff) + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; ++i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, start + len), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if (code < 256) { + val = code + } + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : utf8ToBytes(new Buffer(val, encoding).toString()) + var len = bytes.length + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +function isnan (val) { + return val !== val // eslint-disable-line no-self-compare +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"base64-js":17,"ieee754":57,"isarray":60}],21:[function(require,module,exports){ +module.exports = { + "100": "Continue", + "101": "Switching Protocols", + "102": "Processing", + "200": "OK", + "201": "Created", + "202": "Accepted", + "203": "Non-Authoritative Information", + "204": "No Content", + "205": "Reset Content", + "206": "Partial Content", + "207": "Multi-Status", + "208": "Already Reported", + "226": "IM Used", + "300": "Multiple Choices", + "301": "Moved Permanently", + "302": "Found", + "303": "See Other", + "304": "Not Modified", + "305": "Use Proxy", + "307": "Temporary Redirect", + "308": "Permanent Redirect", + "400": "Bad Request", + "401": "Unauthorized", + "402": "Payment Required", + "403": "Forbidden", + "404": "Not Found", + "405": "Method Not Allowed", + "406": "Not Acceptable", + "407": "Proxy Authentication Required", + "408": "Request Timeout", + "409": "Conflict", + "410": "Gone", + "411": "Length Required", + "412": "Precondition Failed", + "413": "Payload Too Large", + "414": "URI Too Long", + "415": "Unsupported Media Type", + "416": "Range Not Satisfiable", + "417": "Expectation Failed", + "418": "I'm a teapot", + "421": "Misdirected Request", + "422": "Unprocessable Entity", + "423": "Locked", + "424": "Failed Dependency", + "425": "Unordered Collection", + "426": "Upgrade Required", + "428": "Precondition Required", + "429": "Too Many Requests", + "431": "Request Header Fields Too Large", + "451": "Unavailable For Legal Reasons", + "500": "Internal Server Error", + "501": "Not Implemented", + "502": "Bad Gateway", + "503": "Service Unavailable", + "504": "Gateway Timeout", + "505": "HTTP Version Not Supported", + "506": "Variant Also Negotiates", + "507": "Insufficient Storage", + "508": "Loop Detected", + "509": "Bandwidth Limit Exceeded", + "510": "Not Extended", + "511": "Network Authentication Required" +} + +},{}],22:[function(require,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) + +},{"../../is-buffer/index.js":59}],23:[function(require,module,exports){ +// https://d3js.org/d3-array/ Version 1.2.1. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var ascending = function(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +}; + +var bisector = function(compare) { + if (compare.length === 1) compare = ascendingComparator(compare); + return { + left: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) < 0) lo = mid + 1; + else hi = mid; + } + return lo; + }, + right: function(a, x, lo, hi) { + if (lo == null) lo = 0; + if (hi == null) hi = a.length; + while (lo < hi) { + var mid = lo + hi >>> 1; + if (compare(a[mid], x) > 0) hi = mid; + else lo = mid + 1; + } + return lo; + } + }; +}; + +function ascendingComparator(f) { + return function(d, x) { + return ascending(f(d), x); + }; +} + +var ascendingBisect = bisector(ascending); +var bisectRight = ascendingBisect.right; +var bisectLeft = ascendingBisect.left; + +var pairs = function(array, f) { + if (f == null) f = pair; + var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n); + while (i < n) pairs[i] = f(p, p = array[++i]); + return pairs; +}; + +function pair(a, b) { + return [a, b]; +} + +var cross = function(values0, values1, reduce) { + var n0 = values0.length, + n1 = values1.length, + values = new Array(n0 * n1), + i0, + i1, + i, + value0; + + if (reduce == null) reduce = pair; + + for (i0 = i = 0; i0 < n0; ++i0) { + for (value0 = values0[i0], i1 = 0; i1 < n1; ++i1, ++i) { + values[i] = reduce(value0, values1[i1]); + } + } + + return values; +}; + +var descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +}; + +var number = function(x) { + return x === null ? NaN : +x; +}; + +var variance = function(values, valueof) { + var n = values.length, + m = 0, + i = -1, + mean = 0, + value, + delta, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + delta = value - mean; + mean += delta / ++m; + sum += delta * (value - mean); + } + } + } + + if (m > 1) return sum / (m - 1); +}; + +var deviation = function(array, f) { + var v = variance(array, f); + return v ? Math.sqrt(v) : v; +}; + +var extent = function(values, valueof) { + var n = values.length, + i = -1, + value, + min, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null) { + if (min > value) min = value; + if (max < value) max = value; + } + } + } + } + } + + return [min, max]; +}; + +var array = Array.prototype; + +var slice = array.slice; +var map = array.map; + +var constant = function(x) { + return function() { + return x; + }; +}; + +var identity = function(x) { + return x; +}; + +var range = function(start, stop, step) { + start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step; + + var i = -1, + n = Math.max(0, Math.ceil((stop - start) / step)) | 0, + range = new Array(n); + + while (++i < n) { + range[i] = start + i * step; + } + + return range; +}; + +var e10 = Math.sqrt(50); +var e5 = Math.sqrt(10); +var e2 = Math.sqrt(2); + +var ticks = function(start, stop, count) { + var reverse, + i = -1, + n, + ticks, + step; + + stop = +stop, start = +start, count = +count; + if (start === stop && count > 0) return [start]; + if (reverse = stop < start) n = start, start = stop, stop = n; + if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return []; + + if (step > 0) { + start = Math.ceil(start / step); + stop = Math.floor(stop / step); + ticks = new Array(n = Math.ceil(stop - start + 1)); + while (++i < n) ticks[i] = (start + i) * step; + } else { + start = Math.floor(start * step); + stop = Math.ceil(stop * step); + ticks = new Array(n = Math.ceil(start - stop + 1)); + while (++i < n) ticks[i] = (start - i) / step; + } + + if (reverse) ticks.reverse(); + + return ticks; +}; + +function tickIncrement(start, stop, count) { + var step = (stop - start) / Math.max(0, count), + power = Math.floor(Math.log(step) / Math.LN10), + error = step / Math.pow(10, power); + return power >= 0 + ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) + : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1); +} + +function tickStep(start, stop, count) { + var step0 = Math.abs(stop - start) / Math.max(0, count), + step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)), + error = step0 / step1; + if (error >= e10) step1 *= 10; + else if (error >= e5) step1 *= 5; + else if (error >= e2) step1 *= 2; + return stop < start ? -step1 : step1; +} + +var sturges = function(values) { + return Math.ceil(Math.log(values.length) / Math.LN2) + 1; +}; + +var histogram = function() { + var value = identity, + domain = extent, + threshold = sturges; + + function histogram(data) { + var i, + n = data.length, + x, + values = new Array(n); + + for (i = 0; i < n; ++i) { + values[i] = value(data[i], i, data); + } + + var xz = domain(values), + x0 = xz[0], + x1 = xz[1], + tz = threshold(values, x0, x1); + + // Convert number of thresholds into uniform thresholds. + if (!Array.isArray(tz)) { + tz = tickStep(x0, x1, tz); + tz = range(Math.ceil(x0 / tz) * tz, Math.floor(x1 / tz) * tz, tz); // exclusive + } + + // Remove any thresholds outside the domain. + var m = tz.length; + while (tz[0] <= x0) tz.shift(), --m; + while (tz[m - 1] > x1) tz.pop(), --m; + + var bins = new Array(m + 1), + bin; + + // Initialize bins. + for (i = 0; i <= m; ++i) { + bin = bins[i] = []; + bin.x0 = i > 0 ? tz[i - 1] : x0; + bin.x1 = i < m ? tz[i] : x1; + } + + // Assign data to bins by value, ignoring any outside the domain. + for (i = 0; i < n; ++i) { + x = values[i]; + if (x0 <= x && x <= x1) { + bins[bisectRight(tz, x, 0, m)].push(data[i]); + } + } + + return bins; + } + + histogram.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant(_), histogram) : value; + }; + + histogram.domain = function(_) { + return arguments.length ? (domain = typeof _ === "function" ? _ : constant([_[0], _[1]]), histogram) : domain; + }; + + histogram.thresholds = function(_) { + return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant(slice.call(_)) : constant(_), histogram) : threshold; + }; + + return histogram; +}; + +var quantile = function(values, p, valueof) { + if (valueof == null) valueof = number; + if (!(n = values.length)) return; + if ((p = +p) <= 0 || n < 2) return +valueof(values[0], 0, values); + if (p >= 1) return +valueof(values[n - 1], n - 1, values); + var n, + i = (n - 1) * p, + i0 = Math.floor(i), + value0 = +valueof(values[i0], i0, values), + value1 = +valueof(values[i0 + 1], i0 + 1, values); + return value0 + (value1 - value0) * (i - i0); +}; + +var freedmanDiaconis = function(values, min, max) { + values = map.call(values, number).sort(ascending); + return Math.ceil((max - min) / (2 * (quantile(values, 0.75) - quantile(values, 0.25)) * Math.pow(values.length, -1 / 3))); +}; + +var scott = function(values, min, max) { + return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3))); +}; + +var max = function(values, valueof) { + var n = values.length, + i = -1, + value, + max; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && value > max) { + max = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + max = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && value > max) { + max = value; + } + } + } + } + } + + return max; +}; + +var mean = function(values, valueof) { + var n = values.length, + m = n, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) sum += value; + else --m; + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) sum += value; + else --m; + } + } + + if (m) return sum / m; +}; + +var median = function(values, valueof) { + var n = values.length, + i = -1, + value, + numbers = []; + + if (valueof == null) { + while (++i < n) { + if (!isNaN(value = number(values[i]))) { + numbers.push(value); + } + } + } + + else { + while (++i < n) { + if (!isNaN(value = number(valueof(values[i], i, values)))) { + numbers.push(value); + } + } + } + + return quantile(numbers.sort(ascending), 0.5); +}; + +var merge = function(arrays) { + var n = arrays.length, + m, + i = -1, + j = 0, + merged, + array; + + while (++i < n) j += arrays[i].length; + merged = new Array(j); + + while (--n >= 0) { + array = arrays[n]; + m = array.length; + while (--m >= 0) { + merged[--j] = array[m]; + } + } + + return merged; +}; + +var min = function(values, valueof) { + var n = values.length, + i = -1, + value, + min; + + if (valueof == null) { + while (++i < n) { // Find the first comparable value. + if ((value = values[i]) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = values[i]) != null && min > value) { + min = value; + } + } + } + } + } + + else { + while (++i < n) { // Find the first comparable value. + if ((value = valueof(values[i], i, values)) != null && value >= value) { + min = value; + while (++i < n) { // Compare the remaining values. + if ((value = valueof(values[i], i, values)) != null && min > value) { + min = value; + } + } + } + } + } + + return min; +}; + +var permute = function(array, indexes) { + var i = indexes.length, permutes = new Array(i); + while (i--) permutes[i] = array[indexes[i]]; + return permutes; +}; + +var scan = function(values, compare) { + if (!(n = values.length)) return; + var n, + i = 0, + j = 0, + xi, + xj = values[j]; + + if (compare == null) compare = ascending; + + while (++i < n) { + if (compare(xi = values[i], xj) < 0 || compare(xj, xj) !== 0) { + xj = xi, j = i; + } + } + + if (compare(xj, xj) === 0) return j; +}; + +var shuffle = function(array, i0, i1) { + var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0), + t, + i; + + while (m) { + i = Math.random() * m-- | 0; + t = array[m + i0]; + array[m + i0] = array[i + i0]; + array[i + i0] = t; + } + + return array; +}; + +var sum = function(values, valueof) { + var n = values.length, + i = -1, + value, + sum = 0; + + if (valueof == null) { + while (++i < n) { + if (value = +values[i]) sum += value; // Note: zero and null are equivalent. + } + } + + else { + while (++i < n) { + if (value = +valueof(values[i], i, values)) sum += value; + } + } + + return sum; +}; + +var transpose = function(matrix) { + if (!(n = matrix.length)) return []; + for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) { + for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) { + row[j] = matrix[j][i]; + } + } + return transpose; +}; + +function length(d) { + return d.length; +} + +var zip = function() { + return transpose(arguments); +}; + +exports.bisect = bisectRight; +exports.bisectRight = bisectRight; +exports.bisectLeft = bisectLeft; +exports.ascending = ascending; +exports.bisector = bisector; +exports.cross = cross; +exports.descending = descending; +exports.deviation = deviation; +exports.extent = extent; +exports.histogram = histogram; +exports.thresholdFreedmanDiaconis = freedmanDiaconis; +exports.thresholdScott = scott; +exports.thresholdSturges = sturges; +exports.max = max; +exports.mean = mean; +exports.median = median; +exports.merge = merge; +exports.min = min; +exports.pairs = pairs; +exports.permute = permute; +exports.quantile = quantile; +exports.range = range; +exports.scan = scan; +exports.shuffle = shuffle; +exports.sum = sum; +exports.ticks = ticks; +exports.tickIncrement = tickIncrement; +exports.tickStep = tickStep; +exports.transpose = transpose; +exports.variance = variance; +exports.zip = zip; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],24:[function(require,module,exports){ +// https://d3js.org/d3-axis/ Version 1.0.8. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var slice = Array.prototype.slice; + +var identity = function(x) { + return x; +}; + +var top = 1; +var right = 2; +var bottom = 3; +var left = 4; +var epsilon = 1e-6; + +function translateX(x) { + return "translate(" + (x + 0.5) + ",0)"; +} + +function translateY(y) { + return "translate(0," + (y + 0.5) + ")"; +} + +function number(scale) { + return function(d) { + return +scale(d); + }; +} + +function center(scale) { + var offset = Math.max(0, scale.bandwidth() - 1) / 2; // Adjust for 0.5px offset. + if (scale.round()) offset = Math.round(offset); + return function(d) { + return +scale(d) + offset; + }; +} + +function entering() { + return !this.__axis; +} + +function axis(orient, scale) { + var tickArguments = [], + tickValues = null, + tickFormat = null, + tickSizeInner = 6, + tickSizeOuter = 6, + tickPadding = 3, + k = orient === top || orient === left ? -1 : 1, + x = orient === left || orient === right ? "x" : "y", + transform = orient === top || orient === bottom ? translateX : translateY; + + function axis(context) { + var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues, + format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity) : tickFormat, + spacing = Math.max(tickSizeInner, 0) + tickPadding, + range = scale.range(), + range0 = +range[0] + 0.5, + range1 = +range[range.length - 1] + 0.5, + position = (scale.bandwidth ? center : number)(scale.copy()), + selection = context.selection ? context.selection() : context, + path = selection.selectAll(".domain").data([null]), + tick = selection.selectAll(".tick").data(values, scale).order(), + tickExit = tick.exit(), + tickEnter = tick.enter().append("g").attr("class", "tick"), + line = tick.select("line"), + text = tick.select("text"); + + path = path.merge(path.enter().insert("path", ".tick") + .attr("class", "domain") + .attr("stroke", "#000")); + + tick = tick.merge(tickEnter); + + line = line.merge(tickEnter.append("line") + .attr("stroke", "#000") + .attr(x + "2", k * tickSizeInner)); + + text = text.merge(tickEnter.append("text") + .attr("fill", "#000") + .attr(x, k * spacing) + .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em")); + + if (context !== selection) { + path = path.transition(context); + tick = tick.transition(context); + line = line.transition(context); + text = text.transition(context); + + tickExit = tickExit.transition(context) + .attr("opacity", epsilon) + .attr("transform", function(d) { return isFinite(d = position(d)) ? transform(d) : this.getAttribute("transform"); }); + + tickEnter + .attr("opacity", epsilon) + .attr("transform", function(d) { var p = this.parentNode.__axis; return transform(p && isFinite(p = p(d)) ? p : position(d)); }); + } + + tickExit.remove(); + + path + .attr("d", orient === left || orient == right + ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter + : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter); + + tick + .attr("opacity", 1) + .attr("transform", function(d) { return transform(position(d)); }); + + line + .attr(x + "2", k * tickSizeInner); + + text + .attr(x, k * spacing) + .text(format); + + selection.filter(entering) + .attr("fill", "none") + .attr("font-size", 10) + .attr("font-family", "sans-serif") + .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); + + selection + .each(function() { this.__axis = position; }); + } + + axis.scale = function(_) { + return arguments.length ? (scale = _, axis) : scale; + }; + + axis.ticks = function() { + return tickArguments = slice.call(arguments), axis; + }; + + axis.tickArguments = function(_) { + return arguments.length ? (tickArguments = _ == null ? [] : slice.call(_), axis) : tickArguments.slice(); + }; + + axis.tickValues = function(_) { + return arguments.length ? (tickValues = _ == null ? null : slice.call(_), axis) : tickValues && tickValues.slice(); + }; + + axis.tickFormat = function(_) { + return arguments.length ? (tickFormat = _, axis) : tickFormat; + }; + + axis.tickSize = function(_) { + return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner; + }; + + axis.tickSizeInner = function(_) { + return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner; + }; + + axis.tickSizeOuter = function(_) { + return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter; + }; + + axis.tickPadding = function(_) { + return arguments.length ? (tickPadding = +_, axis) : tickPadding; + }; + + return axis; +} + +function axisTop(scale) { + return axis(top, scale); +} + +function axisRight(scale) { + return axis(right, scale); +} + +function axisBottom(scale) { + return axis(bottom, scale); +} + +function axisLeft(scale) { + return axis(left, scale); +} + +exports.axisTop = axisTop; +exports.axisRight = axisRight; +exports.axisBottom = axisBottom; +exports.axisLeft = axisLeft; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],25:[function(require,module,exports){ +// https://d3js.org/d3-brush/ Version 1.0.4. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-drag'), require('d3-interpolate'), require('d3-selection'), require('d3-transition')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-drag', 'd3-interpolate', 'd3-selection', 'd3-transition'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3)); +}(this, (function (exports,d3Dispatch,d3Drag,d3Interpolate,d3Selection,d3Transition) { 'use strict'; + +var constant = function(x) { + return function() { + return x; + }; +}; + +var BrushEvent = function(target, type, selection) { + this.target = target; + this.type = type; + this.selection = selection; +}; + +function nopropagation() { + d3Selection.event.stopImmediatePropagation(); +} + +var noevent = function() { + d3Selection.event.preventDefault(); + d3Selection.event.stopImmediatePropagation(); +}; + +var MODE_DRAG = {name: "drag"}; +var MODE_SPACE = {name: "space"}; +var MODE_HANDLE = {name: "handle"}; +var MODE_CENTER = {name: "center"}; + +var X = { + name: "x", + handles: ["e", "w"].map(type), + input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; }, + output: function(xy) { return xy && [xy[0][0], xy[1][0]]; } +}; + +var Y = { + name: "y", + handles: ["n", "s"].map(type), + input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; }, + output: function(xy) { return xy && [xy[0][1], xy[1][1]]; } +}; + +var XY = { + name: "xy", + handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type), + input: function(xy) { return xy; }, + output: function(xy) { return xy; } +}; + +var cursors = { + overlay: "crosshair", + selection: "move", + n: "ns-resize", + e: "ew-resize", + s: "ns-resize", + w: "ew-resize", + nw: "nwse-resize", + ne: "nesw-resize", + se: "nwse-resize", + sw: "nesw-resize" +}; + +var flipX = { + e: "w", + w: "e", + nw: "ne", + ne: "nw", + se: "sw", + sw: "se" +}; + +var flipY = { + n: "s", + s: "n", + nw: "sw", + ne: "se", + se: "ne", + sw: "nw" +}; + +var signsX = { + overlay: +1, + selection: +1, + n: null, + e: +1, + s: null, + w: -1, + nw: -1, + ne: +1, + se: +1, + sw: -1 +}; + +var signsY = { + overlay: +1, + selection: +1, + n: -1, + e: null, + s: +1, + w: null, + nw: -1, + ne: -1, + se: +1, + sw: +1 +}; + +function type(t) { + return {type: t}; +} + +// Ignore right-click, since that should open the context menu. +function defaultFilter() { + return !d3Selection.event.button; +} + +function defaultExtent() { + var svg = this.ownerSVGElement || this; + return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]]; +} + +// Like d3.local, but with the name “__brush” rather than auto-generated. +function local(node) { + while (!node.__brush) if (!(node = node.parentNode)) return; + return node.__brush; +} + +function empty(extent) { + return extent[0][0] === extent[1][0] + || extent[0][1] === extent[1][1]; +} + +function brushSelection(node) { + var state = node.__brush; + return state ? state.dim.output(state.selection) : null; +} + +function brushX() { + return brush$1(X); +} + +function brushY() { + return brush$1(Y); +} + +var brush = function() { + return brush$1(XY); +}; + +function brush$1(dim) { + var extent = defaultExtent, + filter = defaultFilter, + listeners = d3Dispatch.dispatch(brush, "start", "brush", "end"), + handleSize = 6, + touchending; + + function brush(group) { + var overlay = group + .property("__brush", initialize) + .selectAll(".overlay") + .data([type("overlay")]); + + overlay.enter().append("rect") + .attr("class", "overlay") + .attr("pointer-events", "all") + .attr("cursor", cursors.overlay) + .merge(overlay) + .each(function() { + var extent = local(this).extent; + d3Selection.select(this) + .attr("x", extent[0][0]) + .attr("y", extent[0][1]) + .attr("width", extent[1][0] - extent[0][0]) + .attr("height", extent[1][1] - extent[0][1]); + }); + + group.selectAll(".selection") + .data([type("selection")]) + .enter().append("rect") + .attr("class", "selection") + .attr("cursor", cursors.selection) + .attr("fill", "#777") + .attr("fill-opacity", 0.3) + .attr("stroke", "#fff") + .attr("shape-rendering", "crispEdges"); + + var handle = group.selectAll(".handle") + .data(dim.handles, function(d) { return d.type; }); + + handle.exit().remove(); + + handle.enter().append("rect") + .attr("class", function(d) { return "handle handle--" + d.type; }) + .attr("cursor", function(d) { return cursors[d.type]; }); + + group + .each(redraw) + .attr("fill", "none") + .attr("pointer-events", "all") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)") + .on("mousedown.brush touchstart.brush", started); + } + + brush.move = function(group, selection) { + if (group.selection) { + group + .on("start.brush", function() { emitter(this, arguments).beforestart().start(); }) + .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); }) + .tween("brush", function() { + var that = this, + state = that.__brush, + emit = emitter(that, arguments), + selection0 = state.selection, + selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent), + i = d3Interpolate.interpolate(selection0, selection1); + + function tween(t) { + state.selection = t === 1 && empty(selection1) ? null : i(t); + redraw.call(that); + emit.brush(); + } + + return selection0 && selection1 ? tween : tween(1); + }); + } else { + group + .each(function() { + var that = this, + args = arguments, + state = that.__brush, + selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent), + emit = emitter(that, args).beforestart(); + + d3Transition.interrupt(that); + state.selection = selection1 == null || empty(selection1) ? null : selection1; + redraw.call(that); + emit.start().brush().end(); + }); + } + }; + + function redraw() { + var group = d3Selection.select(this), + selection = local(this).selection; + + if (selection) { + group.selectAll(".selection") + .style("display", null) + .attr("x", selection[0][0]) + .attr("y", selection[0][1]) + .attr("width", selection[1][0] - selection[0][0]) + .attr("height", selection[1][1] - selection[0][1]); + + group.selectAll(".handle") + .style("display", null) + .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; }) + .attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; }) + .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; }) + .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; }); + } + + else { + group.selectAll(".selection,.handle") + .style("display", "none") + .attr("x", null) + .attr("y", null) + .attr("width", null) + .attr("height", null); + } + } + + function emitter(that, args) { + return that.__brush.emitter || new Emitter(that, args); + } + + function Emitter(that, args) { + this.that = that; + this.args = args; + this.state = that.__brush; + this.active = 0; + } + + Emitter.prototype = { + beforestart: function() { + if (++this.active === 1) this.state.emitter = this, this.starting = true; + return this; + }, + start: function() { + if (this.starting) this.starting = false, this.emit("start"); + return this; + }, + brush: function() { + this.emit("brush"); + return this; + }, + end: function() { + if (--this.active === 0) delete this.state.emitter, this.emit("end"); + return this; + }, + emit: function(type) { + d3Selection.customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function started() { + if (d3Selection.event.touches) { if (d3Selection.event.changedTouches.length < d3Selection.event.touches.length) return noevent(); } + else if (touchending) return; + if (!filter.apply(this, arguments)) return; + + var that = this, + type = d3Selection.event.target.__data__.type, + mode = (d3Selection.event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (d3Selection.event.altKey ? MODE_CENTER : MODE_HANDLE), + signX = dim === Y ? null : signsX[type], + signY = dim === X ? null : signsY[type], + state = local(that), + extent = state.extent, + selection = state.selection, + W = extent[0][0], w0, w1, + N = extent[0][1], n0, n1, + E = extent[1][0], e0, e1, + S = extent[1][1], s0, s1, + dx, + dy, + moving, + shifting = signX && signY && d3Selection.event.shiftKey, + lockX, + lockY, + point0 = d3Selection.mouse(that), + point = point0, + emit = emitter(that, arguments).beforestart(); + + if (type === "overlay") { + state.selection = selection = [ + [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]], + [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0] + ]; + } else { + w0 = selection[0][0]; + n0 = selection[0][1]; + e0 = selection[1][0]; + s0 = selection[1][1]; + } + + w1 = w0; + n1 = n0; + e1 = e0; + s1 = s0; + + var group = d3Selection.select(that) + .attr("pointer-events", "none"); + + var overlay = group.selectAll(".overlay") + .attr("cursor", cursors[type]); + + if (d3Selection.event.touches) { + group + .on("touchmove.brush", moved, true) + .on("touchend.brush touchcancel.brush", ended, true); + } else { + var view = d3Selection.select(d3Selection.event.view) + .on("keydown.brush", keydowned, true) + .on("keyup.brush", keyupped, true) + .on("mousemove.brush", moved, true) + .on("mouseup.brush", ended, true); + + d3Drag.dragDisable(d3Selection.event.view); + } + + nopropagation(); + d3Transition.interrupt(that); + redraw.call(that); + emit.start(); + + function moved() { + var point1 = d3Selection.mouse(that); + if (shifting && !lockX && !lockY) { + if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true; + else lockX = true; + } + point = point1; + moving = true; + noevent(); + move(); + } + + function move() { + var t; + + dx = point[0] - point0[0]; + dy = point[1] - point0[1]; + + switch (mode) { + case MODE_SPACE: + case MODE_DRAG: { + if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx; + if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy; + break; + } + case MODE_HANDLE: { + if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0; + else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx; + if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0; + else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy; + break; + } + case MODE_CENTER: { + if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX)); + if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY)); + break; + } + } + + if (e1 < w1) { + signX *= -1; + t = w0, w0 = e0, e0 = t; + t = w1, w1 = e1, e1 = t; + if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]); + } + + if (s1 < n1) { + signY *= -1; + t = n0, n0 = s0, s0 = t; + t = n1, n1 = s1, s1 = t; + if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]); + } + + if (state.selection) selection = state.selection; // May be set by brush.move! + if (lockX) w1 = selection[0][0], e1 = selection[1][0]; + if (lockY) n1 = selection[0][1], s1 = selection[1][1]; + + if (selection[0][0] !== w1 + || selection[0][1] !== n1 + || selection[1][0] !== e1 + || selection[1][1] !== s1) { + state.selection = [[w1, n1], [e1, s1]]; + redraw.call(that); + emit.brush(); + } + } + + function ended() { + nopropagation(); + if (d3Selection.event.touches) { + if (d3Selection.event.touches.length) return; + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + group.on("touchmove.brush touchend.brush touchcancel.brush", null); + } else { + d3Drag.dragEnable(d3Selection.event.view, moving); + view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null); + } + group.attr("pointer-events", "all"); + overlay.attr("cursor", cursors.overlay); + if (state.selection) selection = state.selection; // May be set by brush.move (on start)! + if (empty(selection)) state.selection = null, redraw.call(that); + emit.end(); + } + + function keydowned() { + switch (d3Selection.event.keyCode) { + case 16: { // SHIFT + shifting = signX && signY; + break; + } + case 18: { // ALT + if (mode === MODE_HANDLE) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + move(); + } + break; + } + case 32: { // SPACE; takes priority over ALT + if (mode === MODE_HANDLE || mode === MODE_CENTER) { + if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx; + if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy; + mode = MODE_SPACE; + overlay.attr("cursor", cursors.selection); + move(); + } + break; + } + default: return; + } + noevent(); + } + + function keyupped() { + switch (d3Selection.event.keyCode) { + case 16: { // SHIFT + if (shifting) { + lockX = lockY = shifting = false; + move(); + } + break; + } + case 18: { // ALT + if (mode === MODE_CENTER) { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + move(); + } + break; + } + case 32: { // SPACE + if (mode === MODE_SPACE) { + if (d3Selection.event.altKey) { + if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX; + if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY; + mode = MODE_CENTER; + } else { + if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1; + if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1; + mode = MODE_HANDLE; + } + overlay.attr("cursor", cursors[type]); + move(); + } + break; + } + default: return; + } + noevent(); + } + } + + function initialize() { + var state = this.__brush || {selection: null}; + state.extent = extent.apply(this, arguments); + state.dim = dim; + return state; + } + + brush.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent; + }; + + brush.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), brush) : filter; + }; + + brush.handleSize = function(_) { + return arguments.length ? (handleSize = +_, brush) : handleSize; + }; + + brush.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? brush : value; + }; + + return brush; +} + +exports.brush = brush; +exports.brushX = brushX; +exports.brushY = brushY; +exports.brushSelection = brushSelection; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-dispatch":29,"d3-drag":30,"d3-interpolate":37,"d3-selection":45,"d3-transition":51}],26:[function(require,module,exports){ +// https://d3js.org/d3-chord/ Version 1.0.4. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-path')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-path'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3)); +}(this, (function (exports,d3Array,d3Path) { 'use strict'; + +var cos = Math.cos; +var sin = Math.sin; +var pi = Math.PI; +var halfPi = pi / 2; +var tau = pi * 2; +var max = Math.max; + +function compareValue(compare) { + return function(a, b) { + return compare( + a.source.value + a.target.value, + b.source.value + b.target.value + ); + }; +} + +var chord = function() { + var padAngle = 0, + sortGroups = null, + sortSubgroups = null, + sortChords = null; + + function chord(matrix) { + var n = matrix.length, + groupSums = [], + groupIndex = d3Array.range(n), + subgroupIndex = [], + chords = [], + groups = chords.groups = new Array(n), + subgroups = new Array(n * n), + k, + x, + x0, + dx, + i, + j; + + // Compute the sum. + k = 0, i = -1; while (++i < n) { + x = 0, j = -1; while (++j < n) { + x += matrix[i][j]; + } + groupSums.push(x); + subgroupIndex.push(d3Array.range(n)); + k += x; + } + + // Sort groups… + if (sortGroups) groupIndex.sort(function(a, b) { + return sortGroups(groupSums[a], groupSums[b]); + }); + + // Sort subgroups… + if (sortSubgroups) subgroupIndex.forEach(function(d, i) { + d.sort(function(a, b) { + return sortSubgroups(matrix[i][a], matrix[i][b]); + }); + }); + + // Convert the sum to scaling factor for [0, 2pi]. + // TODO Allow start and end angle to be specified? + // TODO Allow padding to be specified as percentage? + k = max(0, tau - padAngle * n) / k; + dx = k ? padAngle : tau / n; + + // Compute the start and end angle for each group and subgroup. + // Note: Opera has a bug reordering object literal properties! + x = 0, i = -1; while (++i < n) { + x0 = x, j = -1; while (++j < n) { + var di = groupIndex[i], + dj = subgroupIndex[di][j], + v = matrix[di][dj], + a0 = x, + a1 = x += v * k; + subgroups[dj * n + di] = { + index: di, + subindex: dj, + startAngle: a0, + endAngle: a1, + value: v + }; + } + groups[di] = { + index: di, + startAngle: x0, + endAngle: x, + value: groupSums[di] + }; + x += dx; + } + + // Generate chords for each (non-empty) subgroup-subgroup link. + i = -1; while (++i < n) { + j = i - 1; while (++j < n) { + var source = subgroups[j * n + i], + target = subgroups[i * n + j]; + if (source.value || target.value) { + chords.push(source.value < target.value + ? {source: target, target: source} + : {source: source, target: target}); + } + } + } + + return sortChords ? chords.sort(sortChords) : chords; + } + + chord.padAngle = function(_) { + return arguments.length ? (padAngle = max(0, _), chord) : padAngle; + }; + + chord.sortGroups = function(_) { + return arguments.length ? (sortGroups = _, chord) : sortGroups; + }; + + chord.sortSubgroups = function(_) { + return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups; + }; + + chord.sortChords = function(_) { + return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._; + }; + + return chord; +}; + +var slice = Array.prototype.slice; + +var constant = function(x) { + return function() { + return x; + }; +}; + +function defaultSource(d) { + return d.source; +} + +function defaultTarget(d) { + return d.target; +} + +function defaultRadius(d) { + return d.radius; +} + +function defaultStartAngle(d) { + return d.startAngle; +} + +function defaultEndAngle(d) { + return d.endAngle; +} + +var ribbon = function() { + var source = defaultSource, + target = defaultTarget, + radius = defaultRadius, + startAngle = defaultStartAngle, + endAngle = defaultEndAngle, + context = null; + + function ribbon() { + var buffer, + argv = slice.call(arguments), + s = source.apply(this, argv), + t = target.apply(this, argv), + sr = +radius.apply(this, (argv[0] = s, argv)), + sa0 = startAngle.apply(this, argv) - halfPi, + sa1 = endAngle.apply(this, argv) - halfPi, + sx0 = sr * cos(sa0), + sy0 = sr * sin(sa0), + tr = +radius.apply(this, (argv[0] = t, argv)), + ta0 = startAngle.apply(this, argv) - halfPi, + ta1 = endAngle.apply(this, argv) - halfPi; + + if (!context) context = buffer = d3Path.path(); + + context.moveTo(sx0, sy0); + context.arc(0, 0, sr, sa0, sa1); + if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr? + context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0)); + context.arc(0, 0, tr, ta0, ta1); + } + context.quadraticCurveTo(0, 0, sx0, sy0); + context.closePath(); + + if (buffer) return context = null, buffer + "" || null; + } + + ribbon.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), ribbon) : radius; + }; + + ribbon.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), ribbon) : startAngle; + }; + + ribbon.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), ribbon) : endAngle; + }; + + ribbon.source = function(_) { + return arguments.length ? (source = _, ribbon) : source; + }; + + ribbon.target = function(_) { + return arguments.length ? (target = _, ribbon) : target; + }; + + ribbon.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), ribbon) : context; + }; + + return ribbon; +}; + +exports.chord = chord; +exports.ribbon = ribbon; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-array":23,"d3-path":38}],27:[function(require,module,exports){ +// https://d3js.org/d3-collection/ Version 1.0.4. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var prefix = "$"; + +function Map() {} + +Map.prototype = map.prototype = { + constructor: Map, + has: function(key) { + return (prefix + key) in this; + }, + get: function(key) { + return this[prefix + key]; + }, + set: function(key, value) { + this[prefix + key] = value; + return this; + }, + remove: function(key) { + var property = prefix + key; + return property in this && delete this[property]; + }, + clear: function() { + for (var property in this) if (property[0] === prefix) delete this[property]; + }, + keys: function() { + var keys = []; + for (var property in this) if (property[0] === prefix) keys.push(property.slice(1)); + return keys; + }, + values: function() { + var values = []; + for (var property in this) if (property[0] === prefix) values.push(this[property]); + return values; + }, + entries: function() { + var entries = []; + for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]}); + return entries; + }, + size: function() { + var size = 0; + for (var property in this) if (property[0] === prefix) ++size; + return size; + }, + empty: function() { + for (var property in this) if (property[0] === prefix) return false; + return true; + }, + each: function(f) { + for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this); + } +}; + +function map(object, f) { + var map = new Map; + + // Copy constructor. + if (object instanceof Map) object.each(function(value, key) { map.set(key, value); }); + + // Index array by numeric index or specified key function. + else if (Array.isArray(object)) { + var i = -1, + n = object.length, + o; + + if (f == null) while (++i < n) map.set(i, object[i]); + else while (++i < n) map.set(f(o = object[i], i, object), o); + } + + // Convert object to map. + else if (object) for (var key in object) map.set(key, object[key]); + + return map; +} + +var nest = function() { + var keys = [], + sortKeys = [], + sortValues, + rollup, + nest; + + function apply(array, depth, createResult, setResult) { + if (depth >= keys.length) { + if (sortValues != null) array.sort(sortValues); + return rollup != null ? rollup(array) : array; + } + + var i = -1, + n = array.length, + key = keys[depth++], + keyValue, + value, + valuesByKey = map(), + values, + result = createResult(); + + while (++i < n) { + if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) { + values.push(value); + } else { + valuesByKey.set(keyValue, [value]); + } + } + + valuesByKey.each(function(values, key) { + setResult(result, key, apply(values, depth, createResult, setResult)); + }); + + return result; + } + + function entries(map$$1, depth) { + if (++depth > keys.length) return map$$1; + var array, sortKey = sortKeys[depth - 1]; + if (rollup != null && depth >= keys.length) array = map$$1.entries(); + else array = [], map$$1.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); }); + return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array; + } + + return nest = { + object: function(array) { return apply(array, 0, createObject, setObject); }, + map: function(array) { return apply(array, 0, createMap, setMap); }, + entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); }, + key: function(d) { keys.push(d); return nest; }, + sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; }, + sortValues: function(order) { sortValues = order; return nest; }, + rollup: function(f) { rollup = f; return nest; } + }; +}; + +function createObject() { + return {}; +} + +function setObject(object, key, value) { + object[key] = value; +} + +function createMap() { + return map(); +} + +function setMap(map$$1, key, value) { + map$$1.set(key, value); +} + +function Set() {} + +var proto = map.prototype; + +Set.prototype = set.prototype = { + constructor: Set, + has: proto.has, + add: function(value) { + value += ""; + this[prefix + value] = value; + return this; + }, + remove: proto.remove, + clear: proto.clear, + values: proto.keys, + size: proto.size, + empty: proto.empty, + each: proto.each +}; + +function set(object, f) { + var set = new Set; + + // Copy constructor. + if (object instanceof Set) object.each(function(value) { set.add(value); }); + + // Otherwise, assume it’s an array. + else if (object) { + var i = -1, n = object.length; + if (f == null) while (++i < n) set.add(object[i]); + else while (++i < n) set.add(f(object[i], i, object)); + } + + return set; +} + +var keys = function(map) { + var keys = []; + for (var key in map) keys.push(key); + return keys; +}; + +var values = function(map) { + var values = []; + for (var key in map) values.push(map[key]); + return values; +}; + +var entries = function(map) { + var entries = []; + for (var key in map) entries.push({key: key, value: map[key]}); + return entries; +}; + +exports.nest = nest; +exports.set = set; +exports.map = map; +exports.keys = keys; +exports.values = values; +exports.entries = entries; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],28:[function(require,module,exports){ +// https://d3js.org/d3-color/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var define = function(constructor, factory, prototype) { + constructor.prototype = factory.prototype = prototype; + prototype.constructor = constructor; +}; + +function extend(parent, definition) { + var prototype = Object.create(parent.prototype); + for (var key in definition) prototype[key] = definition[key]; + return prototype; +} + +function Color() {} + +var darker = 0.7; +var brighter = 1 / darker; + +var reI = "\\s*([+-]?\\d+)\\s*"; +var reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*"; +var reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*"; +var reHex3 = /^#([0-9a-f]{3})$/; +var reHex6 = /^#([0-9a-f]{6})$/; +var reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"); +var reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"); +var reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"); +var reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"); +var reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"); +var reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$"); + +var named = { + aliceblue: 0xf0f8ff, + antiquewhite: 0xfaebd7, + aqua: 0x00ffff, + aquamarine: 0x7fffd4, + azure: 0xf0ffff, + beige: 0xf5f5dc, + bisque: 0xffe4c4, + black: 0x000000, + blanchedalmond: 0xffebcd, + blue: 0x0000ff, + blueviolet: 0x8a2be2, + brown: 0xa52a2a, + burlywood: 0xdeb887, + cadetblue: 0x5f9ea0, + chartreuse: 0x7fff00, + chocolate: 0xd2691e, + coral: 0xff7f50, + cornflowerblue: 0x6495ed, + cornsilk: 0xfff8dc, + crimson: 0xdc143c, + cyan: 0x00ffff, + darkblue: 0x00008b, + darkcyan: 0x008b8b, + darkgoldenrod: 0xb8860b, + darkgray: 0xa9a9a9, + darkgreen: 0x006400, + darkgrey: 0xa9a9a9, + darkkhaki: 0xbdb76b, + darkmagenta: 0x8b008b, + darkolivegreen: 0x556b2f, + darkorange: 0xff8c00, + darkorchid: 0x9932cc, + darkred: 0x8b0000, + darksalmon: 0xe9967a, + darkseagreen: 0x8fbc8f, + darkslateblue: 0x483d8b, + darkslategray: 0x2f4f4f, + darkslategrey: 0x2f4f4f, + darkturquoise: 0x00ced1, + darkviolet: 0x9400d3, + deeppink: 0xff1493, + deepskyblue: 0x00bfff, + dimgray: 0x696969, + dimgrey: 0x696969, + dodgerblue: 0x1e90ff, + firebrick: 0xb22222, + floralwhite: 0xfffaf0, + forestgreen: 0x228b22, + fuchsia: 0xff00ff, + gainsboro: 0xdcdcdc, + ghostwhite: 0xf8f8ff, + gold: 0xffd700, + goldenrod: 0xdaa520, + gray: 0x808080, + green: 0x008000, + greenyellow: 0xadff2f, + grey: 0x808080, + honeydew: 0xf0fff0, + hotpink: 0xff69b4, + indianred: 0xcd5c5c, + indigo: 0x4b0082, + ivory: 0xfffff0, + khaki: 0xf0e68c, + lavender: 0xe6e6fa, + lavenderblush: 0xfff0f5, + lawngreen: 0x7cfc00, + lemonchiffon: 0xfffacd, + lightblue: 0xadd8e6, + lightcoral: 0xf08080, + lightcyan: 0xe0ffff, + lightgoldenrodyellow: 0xfafad2, + lightgray: 0xd3d3d3, + lightgreen: 0x90ee90, + lightgrey: 0xd3d3d3, + lightpink: 0xffb6c1, + lightsalmon: 0xffa07a, + lightseagreen: 0x20b2aa, + lightskyblue: 0x87cefa, + lightslategray: 0x778899, + lightslategrey: 0x778899, + lightsteelblue: 0xb0c4de, + lightyellow: 0xffffe0, + lime: 0x00ff00, + limegreen: 0x32cd32, + linen: 0xfaf0e6, + magenta: 0xff00ff, + maroon: 0x800000, + mediumaquamarine: 0x66cdaa, + mediumblue: 0x0000cd, + mediumorchid: 0xba55d3, + mediumpurple: 0x9370db, + mediumseagreen: 0x3cb371, + mediumslateblue: 0x7b68ee, + mediumspringgreen: 0x00fa9a, + mediumturquoise: 0x48d1cc, + mediumvioletred: 0xc71585, + midnightblue: 0x191970, + mintcream: 0xf5fffa, + mistyrose: 0xffe4e1, + moccasin: 0xffe4b5, + navajowhite: 0xffdead, + navy: 0x000080, + oldlace: 0xfdf5e6, + olive: 0x808000, + olivedrab: 0x6b8e23, + orange: 0xffa500, + orangered: 0xff4500, + orchid: 0xda70d6, + palegoldenrod: 0xeee8aa, + palegreen: 0x98fb98, + paleturquoise: 0xafeeee, + palevioletred: 0xdb7093, + papayawhip: 0xffefd5, + peachpuff: 0xffdab9, + peru: 0xcd853f, + pink: 0xffc0cb, + plum: 0xdda0dd, + powderblue: 0xb0e0e6, + purple: 0x800080, + rebeccapurple: 0x663399, + red: 0xff0000, + rosybrown: 0xbc8f8f, + royalblue: 0x4169e1, + saddlebrown: 0x8b4513, + salmon: 0xfa8072, + sandybrown: 0xf4a460, + seagreen: 0x2e8b57, + seashell: 0xfff5ee, + sienna: 0xa0522d, + silver: 0xc0c0c0, + skyblue: 0x87ceeb, + slateblue: 0x6a5acd, + slategray: 0x708090, + slategrey: 0x708090, + snow: 0xfffafa, + springgreen: 0x00ff7f, + steelblue: 0x4682b4, + tan: 0xd2b48c, + teal: 0x008080, + thistle: 0xd8bfd8, + tomato: 0xff6347, + turquoise: 0x40e0d0, + violet: 0xee82ee, + wheat: 0xf5deb3, + white: 0xffffff, + whitesmoke: 0xf5f5f5, + yellow: 0xffff00, + yellowgreen: 0x9acd32 +}; + +define(Color, color, { + displayable: function() { + return this.rgb().displayable(); + }, + toString: function() { + return this.rgb() + ""; + } +}); + +function color(format) { + var m; + format = (format + "").trim().toLowerCase(); + return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00 + : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000 + : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0) + : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%) + : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1) + : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1) + : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%) + : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1) + : named.hasOwnProperty(format) ? rgbn(named[format]) + : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) + : null; +} + +function rgbn(n) { + return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1); +} + +function rgba(r, g, b, a) { + if (a <= 0) r = g = b = NaN; + return new Rgb(r, g, b, a); +} + +function rgbConvert(o) { + if (!(o instanceof Color)) o = color(o); + if (!o) return new Rgb; + o = o.rgb(); + return new Rgb(o.r, o.g, o.b, o.opacity); +} + +function rgb(r, g, b, opacity) { + return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity); +} + +function Rgb(r, g, b, opacity) { + this.r = +r; + this.g = +g; + this.b = +b; + this.opacity = +opacity; +} + +define(Rgb, rgb, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity); + }, + rgb: function() { + return this; + }, + displayable: function() { + return (0 <= this.r && this.r <= 255) + && (0 <= this.g && this.g <= 255) + && (0 <= this.b && this.b <= 255) + && (0 <= this.opacity && this.opacity <= 1); + }, + toString: function() { + var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a)); + return (a === 1 ? "rgb(" : "rgba(") + + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + + (a === 1 ? ")" : ", " + a + ")"); + } +})); + +function hsla(h, s, l, a) { + if (a <= 0) h = s = l = NaN; + else if (l <= 0 || l >= 1) h = s = NaN; + else if (s <= 0) h = NaN; + return new Hsl(h, s, l, a); +} + +function hslConvert(o) { + if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Color)) o = color(o); + if (!o) return new Hsl; + if (o instanceof Hsl) return o; + o = o.rgb(); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = NaN, + s = max - min, + l = (max + min) / 2; + if (s) { + if (r === max) h = (g - b) / s + (g < b) * 6; + else if (g === max) h = (b - r) / s + 2; + else h = (r - g) / s + 4; + s /= l < 0.5 ? max + min : 2 - max - min; + h *= 60; + } else { + s = l > 0 && l < 1 ? 0 : h; + } + return new Hsl(h, s, l, o.opacity); +} + +function hsl(h, s, l, opacity) { + return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity); +} + +function Hsl(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Hsl, hsl, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Hsl(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = this.h % 360 + (this.h < 0) * 360, + s = isNaN(h) || isNaN(this.s) ? 0 : this.s, + l = this.l, + m2 = l + (l < 0.5 ? l : 1 - l) * s, + m1 = 2 * l - m2; + return new Rgb( + hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), + hsl2rgb(h, m1, m2), + hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), + this.opacity + ); + }, + displayable: function() { + return (0 <= this.s && this.s <= 1 || isNaN(this.s)) + && (0 <= this.l && this.l <= 1) + && (0 <= this.opacity && this.opacity <= 1); + } +})); + +/* From FvD 13.37, CSS Color Module Level 3 */ +function hsl2rgb(h, m1, m2) { + return (h < 60 ? m1 + (m2 - m1) * h / 60 + : h < 180 ? m2 + : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 + : m1) * 255; +} + +var deg2rad = Math.PI / 180; +var rad2deg = 180 / Math.PI; + +var Kn = 18; +var Xn = 0.950470; +var Yn = 1; +var Zn = 1.088830; +var t0 = 4 / 29; +var t1 = 6 / 29; +var t2 = 3 * t1 * t1; +var t3 = t1 * t1 * t1; + +function labConvert(o) { + if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity); + if (o instanceof Hcl) { + var h = o.h * deg2rad; + return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity); + } + if (!(o instanceof Rgb)) o = rgbConvert(o); + var b = rgb2xyz(o.r), + a = rgb2xyz(o.g), + l = rgb2xyz(o.b), + x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn), + y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn), + z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn); + return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity); +} + +function lab(l, a, b, opacity) { + return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity); +} + +function Lab(l, a, b, opacity) { + this.l = +l; + this.a = +a; + this.b = +b; + this.opacity = +opacity; +} + +define(Lab, lab, extend(Color, { + brighter: function(k) { + return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + darker: function(k) { + return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity); + }, + rgb: function() { + var y = (this.l + 16) / 116, + x = isNaN(this.a) ? y : y + this.a / 500, + z = isNaN(this.b) ? y : y - this.b / 200; + y = Yn * lab2xyz(y); + x = Xn * lab2xyz(x); + z = Zn * lab2xyz(z); + return new Rgb( + xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB + xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z), + xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z), + this.opacity + ); + } +})); + +function xyz2lab(t) { + return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; +} + +function lab2xyz(t) { + return t > t1 ? t * t * t : t2 * (t - t0); +} + +function xyz2rgb(x) { + return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); +} + +function rgb2xyz(x) { + return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); +} + +function hclConvert(o) { + if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity); + if (!(o instanceof Lab)) o = labConvert(o); + var h = Math.atan2(o.b, o.a) * rad2deg; + return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity); +} + +function hcl(h, c, l, opacity) { + return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity); +} + +function Hcl(h, c, l, opacity) { + this.h = +h; + this.c = +c; + this.l = +l; + this.opacity = +opacity; +} + +define(Hcl, hcl, extend(Color, { + brighter: function(k) { + return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity); + }, + darker: function(k) { + return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity); + }, + rgb: function() { + return labConvert(this).rgb(); + } +})); + +var A = -0.14861; +var B = +1.78277; +var C = -0.29227; +var D = -0.90649; +var E = +1.97294; +var ED = E * D; +var EB = E * B; +var BC_DA = B * C - D * A; + +function cubehelixConvert(o) { + if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity); + if (!(o instanceof Rgb)) o = rgbConvert(o); + var r = o.r / 255, + g = o.g / 255, + b = o.b / 255, + l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), + bl = b - l, + k = (E * (g - l) - C * bl) / D, + s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1 + h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN; + return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity); +} + +function cubehelix(h, s, l, opacity) { + return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity); +} + +function Cubehelix(h, s, l, opacity) { + this.h = +h; + this.s = +s; + this.l = +l; + this.opacity = +opacity; +} + +define(Cubehelix, cubehelix, extend(Color, { + brighter: function(k) { + k = k == null ? brighter : Math.pow(brighter, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + darker: function(k) { + k = k == null ? darker : Math.pow(darker, k); + return new Cubehelix(this.h, this.s, this.l * k, this.opacity); + }, + rgb: function() { + var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad, + l = +this.l, + a = isNaN(this.s) ? 0 : this.s * l * (1 - l), + cosh = Math.cos(h), + sinh = Math.sin(h); + return new Rgb( + 255 * (l + a * (A * cosh + B * sinh)), + 255 * (l + a * (C * cosh + D * sinh)), + 255 * (l + a * (E * cosh)), + this.opacity + ); + } +})); + +exports.color = color; +exports.rgb = rgb; +exports.hsl = hsl; +exports.lab = lab; +exports.hcl = hcl; +exports.cubehelix = cubehelix; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],29:[function(require,module,exports){ +// https://d3js.org/d3-dispatch/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var noop = {value: function() {}}; + +function dispatch() { + for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) { + if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t); + _[t] = []; + } + return new Dispatch(_); +} + +function Dispatch(_) { + this._ = _; +} + +function parseTypenames(typenames, types) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t); + return {type: t, name: name}; + }); +} + +Dispatch.prototype = dispatch.prototype = { + constructor: Dispatch, + on: function(typename, callback) { + var _ = this._, + T = parseTypenames(typename + "", _), + t, + i = -1, + n = T.length; + + // If no callback was specified, return the callback of the given type and name. + if (arguments.length < 2) { + while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t; + return; + } + + // If a type was specified, set the callback for the given type and name. + // Otherwise, if a null callback was specified, remove callbacks of the given name. + if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback); + while (++i < n) { + if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback); + else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null); + } + + return this; + }, + copy: function() { + var copy = {}, _ = this._; + for (var t in _) copy[t] = _[t].slice(); + return new Dispatch(copy); + }, + call: function(type, that) { + if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2]; + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + }, + apply: function(type, that, args) { + if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type); + for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args); + } +}; + +function get(type, name) { + for (var i = 0, n = type.length, c; i < n; ++i) { + if ((c = type[i]).name === name) { + return c.value; + } + } +} + +function set(type, name, callback) { + for (var i = 0, n = type.length; i < n; ++i) { + if (type[i].name === name) { + type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1)); + break; + } + } + if (callback != null) type.push({name: name, value: callback}); + return type; +} + +exports.dispatch = dispatch; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],30:[function(require,module,exports){ +// https://d3js.org/d3-drag/ Version 1.2.1. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-selection')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-selection'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3)); +}(this, (function (exports,d3Dispatch,d3Selection) { 'use strict'; + +function nopropagation() { + d3Selection.event.stopImmediatePropagation(); +} + +var noevent = function() { + d3Selection.event.preventDefault(); + d3Selection.event.stopImmediatePropagation(); +}; + +var nodrag = function(view) { + var root = view.document.documentElement, + selection = d3Selection.select(view).on("dragstart.drag", noevent, true); + if ("onselectstart" in root) { + selection.on("selectstart.drag", noevent, true); + } else { + root.__noselect = root.style.MozUserSelect; + root.style.MozUserSelect = "none"; + } +}; + +function yesdrag(view, noclick) { + var root = view.document.documentElement, + selection = d3Selection.select(view).on("dragstart.drag", null); + if (noclick) { + selection.on("click.drag", noevent, true); + setTimeout(function() { selection.on("click.drag", null); }, 0); + } + if ("onselectstart" in root) { + selection.on("selectstart.drag", null); + } else { + root.style.MozUserSelect = root.__noselect; + delete root.__noselect; + } +} + +var constant = function(x) { + return function() { + return x; + }; +}; + +function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch$$1) { + this.target = target; + this.type = type; + this.subject = subject; + this.identifier = id; + this.active = active; + this.x = x; + this.y = y; + this.dx = dx; + this.dy = dy; + this._ = dispatch$$1; +} + +DragEvent.prototype.on = function() { + var value = this._.on.apply(this._, arguments); + return value === this._ ? this : value; +}; + +// Ignore right-click, since that should open the context menu. +function defaultFilter() { + return !d3Selection.event.button; +} + +function defaultContainer() { + return this.parentNode; +} + +function defaultSubject(d) { + return d == null ? {x: d3Selection.event.x, y: d3Selection.event.y} : d; +} + +function defaultTouchable() { + return "ontouchstart" in this; +} + +var drag = function() { + var filter = defaultFilter, + container = defaultContainer, + subject = defaultSubject, + touchable = defaultTouchable, + gestures = {}, + listeners = d3Dispatch.dispatch("start", "drag", "end"), + active = 0, + mousedownx, + mousedowny, + mousemoving, + touchending, + clickDistance2 = 0; + + function drag(selection) { + selection + .on("mousedown.drag", mousedowned) + .filter(touchable) + .on("touchstart.drag", touchstarted) + .on("touchmove.drag", touchmoved) + .on("touchend.drag touchcancel.drag", touchended) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var gesture = beforestart("mouse", container.apply(this, arguments), d3Selection.mouse, this, arguments); + if (!gesture) return; + d3Selection.select(d3Selection.event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true); + nodrag(d3Selection.event.view); + nopropagation(); + mousemoving = false; + mousedownx = d3Selection.event.clientX; + mousedowny = d3Selection.event.clientY; + gesture("start"); + } + + function mousemoved() { + noevent(); + if (!mousemoving) { + var dx = d3Selection.event.clientX - mousedownx, dy = d3Selection.event.clientY - mousedowny; + mousemoving = dx * dx + dy * dy > clickDistance2; + } + gestures.mouse("drag"); + } + + function mouseupped() { + d3Selection.select(d3Selection.event.view).on("mousemove.drag mouseup.drag", null); + yesdrag(d3Selection.event.view, mousemoving); + noevent(); + gestures.mouse("end"); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var touches = d3Selection.event.changedTouches, + c = container.apply(this, arguments), + n = touches.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = beforestart(touches[i].identifier, c, d3Selection.touch, this, arguments)) { + nopropagation(); + gesture("start"); + } + } + } + + function touchmoved() { + var touches = d3Selection.event.changedTouches, + n = touches.length, i, gesture; + + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + noevent(); + gesture("drag"); + } + } + } + + function touchended() { + var touches = d3Selection.event.changedTouches, + n = touches.length, i, gesture; + + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed! + for (i = 0; i < n; ++i) { + if (gesture = gestures[touches[i].identifier]) { + nopropagation(); + gesture("end"); + } + } + } + + function beforestart(id, container, point, that, args) { + var p = point(container, id), s, dx, dy, + sublisteners = listeners.copy(); + + if (!d3Selection.customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() { + if ((d3Selection.event.subject = s = subject.apply(that, args)) == null) return false; + dx = s.x - p[0] || 0; + dy = s.y - p[1] || 0; + return true; + })) return; + + return function gesture(type) { + var p0 = p, n; + switch (type) { + case "start": gestures[id] = gesture, n = active++; break; + case "end": delete gestures[id], --active; // nobreak + case "drag": p = point(container, id), n = active; break; + } + d3Selection.customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]); + }; + } + + drag.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter; + }; + + drag.container = function(_) { + return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container; + }; + + drag.subject = function(_) { + return arguments.length ? (subject = typeof _ === "function" ? _ : constant(_), drag) : subject; + }; + + drag.touchable = function(_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), drag) : touchable; + }; + + drag.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? drag : value; + }; + + drag.clickDistance = function(_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2); + }; + + return drag; +}; + +exports.drag = drag; +exports.dragDisable = nodrag; +exports.dragEnable = yesdrag; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-dispatch":29,"d3-selection":45}],31:[function(require,module,exports){ +// https://d3js.org/d3-dsv/ Version 1.0.8. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var EOL = {}; +var EOF = {}; +var QUOTE = 34; +var NEWLINE = 10; +var RETURN = 13; + +function objectConverter(columns) { + return new Function("d", "return {" + columns.map(function(name, i) { + return JSON.stringify(name) + ": d[" + i + "]"; + }).join(",") + "}"); +} + +function customConverter(columns, f) { + var object = objectConverter(columns); + return function(row, i) { + return f(object(row), i, columns); + }; +} + +// Compute unique columns in order of discovery. +function inferColumns(rows) { + var columnSet = Object.create(null), + columns = []; + + rows.forEach(function(row) { + for (var column in row) { + if (!(column in columnSet)) { + columns.push(columnSet[column] = column); + } + } + }); + + return columns; +} + +var dsv = function(delimiter) { + var reFormat = new RegExp("[\"" + delimiter + "\n\r]"), + DELIMITER = delimiter.charCodeAt(0); + + function parse(text, f) { + var convert, columns, rows = parseRows(text, function(row, i) { + if (convert) return convert(row, i - 1); + columns = row, convert = f ? customConverter(row, f) : objectConverter(row); + }); + rows.columns = columns || []; + return rows; + } + + function parseRows(text, f) { + var rows = [], // output rows + N = text.length, + I = 0, // current character index + n = 0, // current line number + t, // current token + eof = N <= 0, // current token followed by EOF? + eol = false; // current token followed by EOL? + + // Strip the trailing newline. + if (text.charCodeAt(N - 1) === NEWLINE) --N; + if (text.charCodeAt(N - 1) === RETURN) --N; + + function token() { + if (eof) return EOF; + if (eol) return eol = false, EOL; + + // Unescape quotes. + var i, j = I, c; + if (text.charCodeAt(j) === QUOTE) { + while (I++ < N && text.charCodeAt(I) !== QUOTE || text.charCodeAt(++I) === QUOTE); + if ((i = I) >= N) eof = true; + else if ((c = text.charCodeAt(I++)) === NEWLINE) eol = true; + else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } + return text.slice(j + 1, i - 1).replace(/""/g, "\""); + } + + // Find next delimiter or newline. + while (I < N) { + if ((c = text.charCodeAt(i = I++)) === NEWLINE) eol = true; + else if (c === RETURN) { eol = true; if (text.charCodeAt(I) === NEWLINE) ++I; } + else if (c !== DELIMITER) continue; + return text.slice(j, i); + } + + // Return last token before EOF. + return eof = true, text.slice(j, N); + } + + while ((t = token()) !== EOF) { + var row = []; + while (t !== EOL && t !== EOF) row.push(t), t = token(); + if (f && (row = f(row, n++)) == null) continue; + rows.push(row); + } + + return rows; + } + + function format(rows, columns) { + if (columns == null) columns = inferColumns(rows); + return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) { + return columns.map(function(column) { + return formatValue(row[column]); + }).join(delimiter); + })).join("\n"); + } + + function formatRows(rows) { + return rows.map(formatRow).join("\n"); + } + + function formatRow(row) { + return row.map(formatValue).join(delimiter); + } + + function formatValue(text) { + return text == null ? "" + : reFormat.test(text += "") ? "\"" + text.replace(/"/g, "\"\"") + "\"" + : text; + } + + return { + parse: parse, + parseRows: parseRows, + format: format, + formatRows: formatRows + }; +}; + +var csv = dsv(","); + +var csvParse = csv.parse; +var csvParseRows = csv.parseRows; +var csvFormat = csv.format; +var csvFormatRows = csv.formatRows; + +var tsv = dsv("\t"); + +var tsvParse = tsv.parse; +var tsvParseRows = tsv.parseRows; +var tsvFormat = tsv.format; +var tsvFormatRows = tsv.formatRows; + +exports.dsvFormat = dsv; +exports.csvParse = csvParse; +exports.csvParseRows = csvParseRows; +exports.csvFormat = csvFormat; +exports.csvFormatRows = csvFormatRows; +exports.tsvParse = tsvParse; +exports.tsvParseRows = tsvParseRows; +exports.tsvFormat = tsvFormat; +exports.tsvFormatRows = tsvFormatRows; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],32:[function(require,module,exports){ +// https://d3js.org/d3-ease/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +function linear(t) { + return +t; +} + +function quadIn(t) { + return t * t; +} + +function quadOut(t) { + return t * (2 - t); +} + +function quadInOut(t) { + return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2; +} + +function cubicIn(t) { + return t * t * t; +} + +function cubicOut(t) { + return --t * t * t + 1; +} + +function cubicInOut(t) { + return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2; +} + +var exponent = 3; + +var polyIn = (function custom(e) { + e = +e; + + function polyIn(t) { + return Math.pow(t, e); + } + + polyIn.exponent = custom; + + return polyIn; +})(exponent); + +var polyOut = (function custom(e) { + e = +e; + + function polyOut(t) { + return 1 - Math.pow(1 - t, e); + } + + polyOut.exponent = custom; + + return polyOut; +})(exponent); + +var polyInOut = (function custom(e) { + e = +e; + + function polyInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2; + } + + polyInOut.exponent = custom; + + return polyInOut; +})(exponent); + +var pi = Math.PI; +var halfPi = pi / 2; + +function sinIn(t) { + return 1 - Math.cos(t * halfPi); +} + +function sinOut(t) { + return Math.sin(t * halfPi); +} + +function sinInOut(t) { + return (1 - Math.cos(pi * t)) / 2; +} + +function expIn(t) { + return Math.pow(2, 10 * t - 10); +} + +function expOut(t) { + return 1 - Math.pow(2, -10 * t); +} + +function expInOut(t) { + return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2; +} + +function circleIn(t) { + return 1 - Math.sqrt(1 - t * t); +} + +function circleOut(t) { + return Math.sqrt(1 - --t * t); +} + +function circleInOut(t) { + return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2; +} + +var b1 = 4 / 11; +var b2 = 6 / 11; +var b3 = 8 / 11; +var b4 = 3 / 4; +var b5 = 9 / 11; +var b6 = 10 / 11; +var b7 = 15 / 16; +var b8 = 21 / 22; +var b9 = 63 / 64; +var b0 = 1 / b1 / b1; + +function bounceIn(t) { + return 1 - bounceOut(1 - t); +} + +function bounceOut(t) { + return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9; +} + +function bounceInOut(t) { + return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2; +} + +var overshoot = 1.70158; + +var backIn = (function custom(s) { + s = +s; + + function backIn(t) { + return t * t * ((s + 1) * t - s); + } + + backIn.overshoot = custom; + + return backIn; +})(overshoot); + +var backOut = (function custom(s) { + s = +s; + + function backOut(t) { + return --t * t * ((s + 1) * t + s) + 1; + } + + backOut.overshoot = custom; + + return backOut; +})(overshoot); + +var backInOut = (function custom(s) { + s = +s; + + function backInOut(t) { + return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2; + } + + backInOut.overshoot = custom; + + return backInOut; +})(overshoot); + +var tau = 2 * Math.PI; +var amplitude = 1; +var period = 0.3; + +var elasticIn = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticIn(t) { + return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p); + } + + elasticIn.amplitude = function(a) { return custom(a, p * tau); }; + elasticIn.period = function(p) { return custom(a, p); }; + + return elasticIn; +})(amplitude, period); + +var elasticOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticOut(t) { + return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p); + } + + elasticOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticOut.period = function(p) { return custom(a, p); }; + + return elasticOut; +})(amplitude, period); + +var elasticInOut = (function custom(a, p) { + var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau); + + function elasticInOut(t) { + return ((t = t * 2 - 1) < 0 + ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p) + : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2; + } + + elasticInOut.amplitude = function(a) { return custom(a, p * tau); }; + elasticInOut.period = function(p) { return custom(a, p); }; + + return elasticInOut; +})(amplitude, period); + +exports.easeLinear = linear; +exports.easeQuad = quadInOut; +exports.easeQuadIn = quadIn; +exports.easeQuadOut = quadOut; +exports.easeQuadInOut = quadInOut; +exports.easeCubic = cubicInOut; +exports.easeCubicIn = cubicIn; +exports.easeCubicOut = cubicOut; +exports.easeCubicInOut = cubicInOut; +exports.easePoly = polyInOut; +exports.easePolyIn = polyIn; +exports.easePolyOut = polyOut; +exports.easePolyInOut = polyInOut; +exports.easeSin = sinInOut; +exports.easeSinIn = sinIn; +exports.easeSinOut = sinOut; +exports.easeSinInOut = sinInOut; +exports.easeExp = expInOut; +exports.easeExpIn = expIn; +exports.easeExpOut = expOut; +exports.easeExpInOut = expInOut; +exports.easeCircle = circleInOut; +exports.easeCircleIn = circleIn; +exports.easeCircleOut = circleOut; +exports.easeCircleInOut = circleInOut; +exports.easeBounce = bounceOut; +exports.easeBounceIn = bounceIn; +exports.easeBounceOut = bounceOut; +exports.easeBounceInOut = bounceInOut; +exports.easeBack = backInOut; +exports.easeBackIn = backIn; +exports.easeBackOut = backOut; +exports.easeBackInOut = backInOut; +exports.easeElastic = elasticOut; +exports.easeElasticIn = elasticIn; +exports.easeElasticOut = elasticOut; +exports.easeElasticInOut = elasticInOut; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],33:[function(require,module,exports){ +// https://d3js.org/d3-force/ Version 1.1.0. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-quadtree'), require('d3-collection'), require('d3-dispatch'), require('d3-timer')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-quadtree', 'd3-collection', 'd3-dispatch', 'd3-timer'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3)); +}(this, (function (exports,d3Quadtree,d3Collection,d3Dispatch,d3Timer) { 'use strict'; + +var center = function(x, y) { + var nodes; + + if (x == null) x = 0; + if (y == null) y = 0; + + function force() { + var i, + n = nodes.length, + node, + sx = 0, + sy = 0; + + for (i = 0; i < n; ++i) { + node = nodes[i], sx += node.x, sy += node.y; + } + + for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) { + node = nodes[i], node.x -= sx, node.y -= sy; + } + } + + force.initialize = function(_) { + nodes = _; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; +}; + +var constant = function(x) { + return function() { + return x; + }; +}; + +var jiggle = function() { + return (Math.random() - 0.5) * 1e-6; +}; + +function x(d) { + return d.x + d.vx; +} + +function y(d) { + return d.y + d.vy; +} + +var collide = function(radius) { + var nodes, + radii, + strength = 1, + iterations = 1; + + if (typeof radius !== "function") radius = constant(radius == null ? 1 : +radius); + + function force() { + var i, n = nodes.length, + tree, + node, + xi, + yi, + ri, + ri2; + + for (var k = 0; k < iterations; ++k) { + tree = d3Quadtree.quadtree(nodes, x, y).visitAfter(prepare); + for (i = 0; i < n; ++i) { + node = nodes[i]; + ri = radii[node.index], ri2 = ri * ri; + xi = node.x + node.vx; + yi = node.y + node.vy; + tree.visit(apply); + } + } + + function apply(quad, x0, y0, x1, y1) { + var data = quad.data, rj = quad.r, r = ri + rj; + if (data) { + if (data.index > node.index) { + var x = xi - data.x - data.vx, + y = yi - data.y - data.vy, + l = x * x + y * y; + if (l < r * r) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + l = (r - (l = Math.sqrt(l))) / l * strength; + node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj)); + node.vy += (y *= l) * r; + data.vx -= x * (r = 1 - r); + data.vy -= y * r; + } + } + return; + } + return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r; + } + } + + function prepare(quad) { + if (quad.data) return quad.r = radii[quad.data.index]; + for (var i = quad.r = 0; i < 4; ++i) { + if (quad[i] && quad[i].r > quad.r) { + quad.r = quad[i].r; + } + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + radii = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], radii[node.index] = +radius(node, i, nodes); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = +_, force) : strength; + }; + + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; + }; + + return force; +}; + +function index(d) { + return d.index; +} + +function find(nodeById, nodeId) { + var node = nodeById.get(nodeId); + if (!node) throw new Error("missing: " + nodeId); + return node; +} + +var link = function(links) { + var id = index, + strength = defaultStrength, + strengths, + distance = constant(30), + distances, + nodes, + count, + bias, + iterations = 1; + + if (links == null) links = []; + + function defaultStrength(link) { + return 1 / Math.min(count[link.source.index], count[link.target.index]); + } + + function force(alpha) { + for (var k = 0, n = links.length; k < iterations; ++k) { + for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) { + link = links[i], source = link.source, target = link.target; + x = target.x + target.vx - source.x - source.vx || jiggle(); + y = target.y + target.vy - source.y - source.vy || jiggle(); + l = Math.sqrt(x * x + y * y); + l = (l - distances[i]) / l * alpha * strengths[i]; + x *= l, y *= l; + target.vx -= x * (b = bias[i]); + target.vy -= y * b; + source.vx += x * (b = 1 - b); + source.vy += y * b; + } + } + } + + function initialize() { + if (!nodes) return; + + var i, + n = nodes.length, + m = links.length, + nodeById = d3Collection.map(nodes, id), + link; + + for (i = 0, count = new Array(n); i < m; ++i) { + link = links[i], link.index = i; + if (typeof link.source !== "object") link.source = find(nodeById, link.source); + if (typeof link.target !== "object") link.target = find(nodeById, link.target); + count[link.source.index] = (count[link.source.index] || 0) + 1; + count[link.target.index] = (count[link.target.index] || 0) + 1; + } + + for (i = 0, bias = new Array(m); i < m; ++i) { + link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]); + } + + strengths = new Array(m), initializeStrength(); + distances = new Array(m), initializeDistance(); + } + + function initializeStrength() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + strengths[i] = +strength(links[i], i, links); + } + } + + function initializeDistance() { + if (!nodes) return; + + for (var i = 0, n = links.length; i < n; ++i) { + distances[i] = +distance(links[i], i, links); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.links = function(_) { + return arguments.length ? (links = _, initialize(), force) : links; + }; + + force.id = function(_) { + return arguments.length ? (id = _, force) : id; + }; + + force.iterations = function(_) { + return arguments.length ? (iterations = +_, force) : iterations; + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initializeStrength(), force) : strength; + }; + + force.distance = function(_) { + return arguments.length ? (distance = typeof _ === "function" ? _ : constant(+_), initializeDistance(), force) : distance; + }; + + return force; +}; + +function x$1(d) { + return d.x; +} + +function y$1(d) { + return d.y; +} + +var initialRadius = 10; +var initialAngle = Math.PI * (3 - Math.sqrt(5)); + +var simulation = function(nodes) { + var simulation, + alpha = 1, + alphaMin = 0.001, + alphaDecay = 1 - Math.pow(alphaMin, 1 / 300), + alphaTarget = 0, + velocityDecay = 0.6, + forces = d3Collection.map(), + stepper = d3Timer.timer(step), + event = d3Dispatch.dispatch("tick", "end"); + + if (nodes == null) nodes = []; + + function step() { + tick(); + event.call("tick", simulation); + if (alpha < alphaMin) { + stepper.stop(); + event.call("end", simulation); + } + } + + function tick() { + var i, n = nodes.length, node; + + alpha += (alphaTarget - alpha) * alphaDecay; + + forces.each(function(force) { + force(alpha); + }); + + for (i = 0; i < n; ++i) { + node = nodes[i]; + if (node.fx == null) node.x += node.vx *= velocityDecay; + else node.x = node.fx, node.vx = 0; + if (node.fy == null) node.y += node.vy *= velocityDecay; + else node.y = node.fy, node.vy = 0; + } + } + + function initializeNodes() { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.index = i; + if (isNaN(node.x) || isNaN(node.y)) { + var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle; + node.x = radius * Math.cos(angle); + node.y = radius * Math.sin(angle); + } + if (isNaN(node.vx) || isNaN(node.vy)) { + node.vx = node.vy = 0; + } + } + } + + function initializeForce(force) { + if (force.initialize) force.initialize(nodes); + return force; + } + + initializeNodes(); + + return simulation = { + tick: tick, + + restart: function() { + return stepper.restart(step), simulation; + }, + + stop: function() { + return stepper.stop(), simulation; + }, + + nodes: function(_) { + return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes; + }, + + alpha: function(_) { + return arguments.length ? (alpha = +_, simulation) : alpha; + }, + + alphaMin: function(_) { + return arguments.length ? (alphaMin = +_, simulation) : alphaMin; + }, + + alphaDecay: function(_) { + return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay; + }, + + alphaTarget: function(_) { + return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget; + }, + + velocityDecay: function(_) { + return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay; + }, + + force: function(name, _) { + return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name); + }, + + find: function(x, y, radius) { + var i = 0, + n = nodes.length, + dx, + dy, + d2, + node, + closest; + + if (radius == null) radius = Infinity; + else radius *= radius; + + for (i = 0; i < n; ++i) { + node = nodes[i]; + dx = x - node.x; + dy = y - node.y; + d2 = dx * dx + dy * dy; + if (d2 < radius) closest = node, radius = d2; + } + + return closest; + }, + + on: function(name, _) { + return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name); + } + }; +}; + +var manyBody = function() { + var nodes, + node, + alpha, + strength = constant(-30), + strengths, + distanceMin2 = 1, + distanceMax2 = Infinity, + theta2 = 0.81; + + function force(_) { + var i, n = nodes.length, tree = d3Quadtree.quadtree(nodes, x$1, y$1).visitAfter(accumulate); + for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply); + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length, node; + strengths = new Array(n); + for (i = 0; i < n; ++i) node = nodes[i], strengths[node.index] = +strength(node, i, nodes); + } + + function accumulate(quad) { + var strength = 0, q, c, weight = 0, x, y, i; + + // For internal nodes, accumulate forces from child quadrants. + if (quad.length) { + for (x = y = i = 0; i < 4; ++i) { + if ((q = quad[i]) && (c = Math.abs(q.value))) { + strength += q.value, weight += c, x += c * q.x, y += c * q.y; + } + } + quad.x = x / weight; + quad.y = y / weight; + } + + // For leaf nodes, accumulate forces from coincident quadrants. + else { + q = quad; + q.x = q.data.x; + q.y = q.data.y; + do strength += strengths[q.data.index]; + while (q = q.next); + } + + quad.value = strength; + } + + function apply(quad, x1, _, x2) { + if (!quad.value) return true; + + var x = quad.x - node.x, + y = quad.y - node.y, + w = x2 - x1, + l = x * x + y * y; + + // Apply the Barnes-Hut approximation if possible. + // Limit forces for very close nodes; randomize direction if coincident. + if (w * w / theta2 < l) { + if (l < distanceMax2) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + node.vx += x * quad.value * alpha / l; + node.vy += y * quad.value * alpha / l; + } + return true; + } + + // Otherwise, process points directly. + else if (quad.length || l >= distanceMax2) return; + + // Limit forces for very close nodes; randomize direction if coincident. + if (quad.data !== node || quad.next) { + if (x === 0) x = jiggle(), l += x * x; + if (y === 0) y = jiggle(), l += y * y; + if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l); + } + + do if (quad.data !== node) { + w = strengths[quad.data.index] * alpha / l; + node.vx += x * w; + node.vy += y * w; + } while (quad = quad.next); + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.distanceMin = function(_) { + return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2); + }; + + force.distanceMax = function(_) { + return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2); + }; + + force.theta = function(_) { + return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2); + }; + + return force; +}; + +var radial = function(radius, x, y) { + var nodes, + strength = constant(0.1), + strengths, + radiuses; + + if (typeof radius !== "function") radius = constant(+radius); + if (x == null) x = 0; + if (y == null) y = 0; + + function force(alpha) { + for (var i = 0, n = nodes.length; i < n; ++i) { + var node = nodes[i], + dx = node.x - x || 1e-6, + dy = node.y - y || 1e-6, + r = Math.sqrt(dx * dx + dy * dy), + k = (radiuses[i] - r) * strengths[i] * alpha / r; + node.vx += dx * k; + node.vy += dy * k; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + radiuses = new Array(n); + for (i = 0; i < n; ++i) { + radiuses[i] = +radius(nodes[i], i, nodes); + strengths[i] = isNaN(radiuses[i]) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _, initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), initialize(), force) : radius; + }; + + force.x = function(_) { + return arguments.length ? (x = +_, force) : x; + }; + + force.y = function(_) { + return arguments.length ? (y = +_, force) : y; + }; + + return force; +}; + +var x$2 = function(x) { + var strength = constant(0.1), + nodes, + strengths, + xz; + + if (typeof x !== "function") x = constant(x == null ? 0 : +x); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + xz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.x = function(_) { + return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), initialize(), force) : x; + }; + + return force; +}; + +var y$2 = function(y) { + var strength = constant(0.1), + nodes, + strengths, + yz; + + if (typeof y !== "function") y = constant(y == null ? 0 : +y); + + function force(alpha) { + for (var i = 0, n = nodes.length, node; i < n; ++i) { + node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha; + } + } + + function initialize() { + if (!nodes) return; + var i, n = nodes.length; + strengths = new Array(n); + yz = new Array(n); + for (i = 0; i < n; ++i) { + strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes); + } + } + + force.initialize = function(_) { + nodes = _; + initialize(); + }; + + force.strength = function(_) { + return arguments.length ? (strength = typeof _ === "function" ? _ : constant(+_), initialize(), force) : strength; + }; + + force.y = function(_) { + return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), initialize(), force) : y; + }; + + return force; +}; + +exports.forceCenter = center; +exports.forceCollide = collide; +exports.forceLink = link; +exports.forceManyBody = manyBody; +exports.forceRadial = radial; +exports.forceSimulation = simulation; +exports.forceX = x$2; +exports.forceY = y$2; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-collection":27,"d3-dispatch":29,"d3-quadtree":40,"d3-timer":49}],34:[function(require,module,exports){ +// https://d3js.org/d3-format/ Version 1.2.2. Copyright 2018 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +// Computes the decimal coefficient and exponent of the specified number x with +// significant digits p, where x is positive and p is in [1, 21] or undefined. +// For example, formatDecimal(1.23) returns ["123", 0]. +var formatDecimal = function(x, p) { + if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity + var i, coefficient = x.slice(0, i); + + // The string returned by toExponential either has the form \d\.\d+e[-+]\d+ + // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). + return [ + coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, + +x.slice(i + 1) + ]; +}; + +var exponent = function(x) { + return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; +}; + +var formatGroup = function(grouping, thousands) { + return function(value, width) { + var i = value.length, + t = [], + j = 0, + g = grouping[0], + length = 0; + + while (i > 0 && g > 0) { + if (length + g + 1 > width) g = Math.max(1, width - length); + t.push(value.substring(i -= g, i + g)); + if ((length += g + 1) > width) break; + g = grouping[j = (j + 1) % grouping.length]; + } + + return t.reverse().join(thousands); + }; +}; + +var formatNumerals = function(numerals) { + return function(value) { + return value.replace(/[0-9]/g, function(i) { + return numerals[+i]; + }); + }; +}; + +var formatDefault = function(x, p) { + x = x.toPrecision(p); + + out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { + switch (x[i]) { + case ".": i0 = i1 = i; break; + case "0": if (i0 === 0) i0 = i; i1 = i; break; + case "e": break out; + default: if (i0 > 0) i0 = 0; break; + } + } + + return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; +}; + +var prefixExponent; + +var formatPrefixAuto = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1], + i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, + n = coefficient.length; + return i === n ? coefficient + : i > n ? coefficient + new Array(i - n + 1).join("0") + : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) + : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y! +}; + +var formatRounded = function(x, p) { + var d = formatDecimal(x, p); + if (!d) return x + ""; + var coefficient = d[0], + exponent = d[1]; + return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient + : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) + : coefficient + new Array(exponent - coefficient.length + 2).join("0"); +}; + +var formatTypes = { + "": formatDefault, + "%": function(x, p) { return (x * 100).toFixed(p); }, + "b": function(x) { return Math.round(x).toString(2); }, + "c": function(x) { return x + ""; }, + "d": function(x) { return Math.round(x).toString(10); }, + "e": function(x, p) { return x.toExponential(p); }, + "f": function(x, p) { return x.toFixed(p); }, + "g": function(x, p) { return x.toPrecision(p); }, + "o": function(x) { return Math.round(x).toString(8); }, + "p": function(x, p) { return formatRounded(x * 100, p); }, + "r": formatRounded, + "s": formatPrefixAuto, + "X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, + "x": function(x) { return Math.round(x).toString(16); } +}; + +// [[fill]align][sign][symbol][0][width][,][.precision][type] +var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; + +function formatSpecifier(specifier) { + return new FormatSpecifier(specifier); +} + +formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof + +function FormatSpecifier(specifier) { + if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); + + var match, + fill = match[1] || " ", + align = match[2] || ">", + sign = match[3] || "-", + symbol = match[4] || "", + zero = !!match[5], + width = match[6] && +match[6], + comma = !!match[7], + precision = match[8] && +match[8].slice(1), + type = match[9] || ""; + + // The "n" type is an alias for ",g". + if (type === "n") comma = true, type = "g"; + + // Map invalid types to the default format. + else if (!formatTypes[type]) type = ""; + + // If zero fill is specified, padding goes after sign and before digits. + if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; + + this.fill = fill; + this.align = align; + this.sign = sign; + this.symbol = symbol; + this.zero = zero; + this.width = width; + this.comma = comma; + this.precision = precision; + this.type = type; +} + +FormatSpecifier.prototype.toString = function() { + return this.fill + + this.align + + this.sign + + this.symbol + + (this.zero ? "0" : "") + + (this.width == null ? "" : Math.max(1, this.width | 0)) + + (this.comma ? "," : "") + + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) + + this.type; +}; + +var identity = function(x) { + return x; +}; + +var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"]; + +var formatLocale = function(locale) { + var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity, + currency = locale.currency, + decimal = locale.decimal, + numerals = locale.numerals ? formatNumerals(locale.numerals) : identity, + percent = locale.percent || "%"; + + function newFormat(specifier) { + specifier = formatSpecifier(specifier); + + var fill = specifier.fill, + align = specifier.align, + sign = specifier.sign, + symbol = specifier.symbol, + zero = specifier.zero, + width = specifier.width, + comma = specifier.comma, + precision = specifier.precision, + type = specifier.type; + + // Compute the prefix and suffix. + // For SI-prefix, the suffix is lazily computed. + var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", + suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? percent : ""; + + // What format function should we use? + // Is this an integer type? + // Can this type generate exponential notation? + var formatType = formatTypes[type], + maybeSuffix = !type || /[defgprs%]/.test(type); + + // Set the default precision if not specified, + // or clamp the specified precision to the supported range. + // For significant precision, it must be in [1, 21]. + // For fixed precision, it must be in [0, 20]. + precision = precision == null ? (type ? 6 : 12) + : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) + : Math.max(0, Math.min(20, precision)); + + function format(value) { + var valuePrefix = prefix, + valueSuffix = suffix, + i, n, c; + + if (type === "c") { + valueSuffix = formatType(value) + valueSuffix; + value = ""; + } else { + value = +value; + + // Perform the initial formatting. + var valueNegative = value < 0; + value = formatType(Math.abs(value), precision); + + // If a negative value rounds to zero during formatting, treat as positive. + if (valueNegative && +value === 0) valueNegative = false; + + // Compute the prefix and suffix. + valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; + valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); + + // Break the formatted value into the integer “value” part that can be + // grouped, and fractional or exponential “suffix” part that is not. + if (maybeSuffix) { + i = -1, n = value.length; + while (++i < n) { + if (c = value.charCodeAt(i), 48 > c || c > 57) { + valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; + value = value.slice(0, i); + break; + } + } + } + } + + // If the fill character is not "0", grouping is applied before padding. + if (comma && !zero) value = group(value, Infinity); + + // Compute the padding. + var length = valuePrefix.length + value.length + valueSuffix.length, + padding = length < width ? new Array(width - length + 1).join(fill) : ""; + + // If the fill character is "0", grouping is applied after padding. + if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; + + // Reconstruct the final output based on the desired alignment. + switch (align) { + case "<": value = valuePrefix + value + valueSuffix + padding; break; + case "=": value = valuePrefix + padding + value + valueSuffix; break; + case "^": value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); break; + default: value = padding + valuePrefix + value + valueSuffix; break; + } + + return numerals(value); + } + + format.toString = function() { + return specifier + ""; + }; + + return format; + } + + function formatPrefix(specifier, value) { + var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), + e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, + k = Math.pow(10, -e), + prefix = prefixes[8 + e / 3]; + return function(value) { + return f(k * value) + prefix; + }; + } + + return { + format: newFormat, + formatPrefix: formatPrefix + }; +}; + +var locale; + + + +defaultLocale({ + decimal: ".", + thousands: ",", + grouping: [3], + currency: ["$", ""] +}); + +function defaultLocale(definition) { + locale = formatLocale(definition); + exports.format = locale.format; + exports.formatPrefix = locale.formatPrefix; + return locale; +} + +var precisionFixed = function(step) { + return Math.max(0, -exponent(Math.abs(step))); +}; + +var precisionPrefix = function(step, value) { + return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step))); +}; + +var precisionRound = function(step, max) { + step = Math.abs(step), max = Math.abs(max) - step; + return Math.max(0, exponent(max) - exponent(step)) + 1; +}; + +exports.formatDefaultLocale = defaultLocale; +exports.formatLocale = formatLocale; +exports.formatSpecifier = formatSpecifier; +exports.precisionFixed = precisionFixed; +exports.precisionPrefix = precisionPrefix; +exports.precisionRound = precisionRound; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],35:[function(require,module,exports){ +// https://d3js.org/d3-geo/ Version 1.9.1. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-array'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3)); +}(this, (function (exports,d3Array) { 'use strict'; + +// Adds floating point numbers with twice the normal precision. +// Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and +// Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) +// 305–363 (1997). +// Code adapted from GeographicLib by Charles F. F. Karney, +// http://geographiclib.sourceforge.net/ + +var adder = function() { + return new Adder; +}; + +function Adder() { + this.reset(); +} + +Adder.prototype = { + constructor: Adder, + reset: function() { + this.s = // rounded value + this.t = 0; // exact error + }, + add: function(y) { + add(temp, y, this.t); + add(this, temp.s, this.s); + if (this.s) this.t += temp.t; + else this.s = temp.t; + }, + valueOf: function() { + return this.s; + } +}; + +var temp = new Adder; + +function add(adder, a, b) { + var x = adder.s = a + b, + bv = x - a, + av = x - bv; + adder.t = (a - av) + (b - bv); +} + +var epsilon = 1e-6; +var epsilon2 = 1e-12; +var pi = Math.PI; +var halfPi = pi / 2; +var quarterPi = pi / 4; +var tau = pi * 2; + +var degrees = 180 / pi; +var radians = pi / 180; + +var abs = Math.abs; +var atan = Math.atan; +var atan2 = Math.atan2; +var cos = Math.cos; +var ceil = Math.ceil; +var exp = Math.exp; + +var log = Math.log; +var pow = Math.pow; +var sin = Math.sin; +var sign = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; }; +var sqrt = Math.sqrt; +var tan = Math.tan; + +function acos(x) { + return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); +} + +function asin(x) { + return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x); +} + +function haversin(x) { + return (x = sin(x / 2)) * x; +} + +function noop() {} + +function streamGeometry(geometry, stream) { + if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { + streamGeometryType[geometry.type](geometry, stream); + } +} + +var streamObjectType = { + Feature: function(object, stream) { + streamGeometry(object.geometry, stream); + }, + FeatureCollection: function(object, stream) { + var features = object.features, i = -1, n = features.length; + while (++i < n) streamGeometry(features[i].geometry, stream); + } +}; + +var streamGeometryType = { + Sphere: function(object, stream) { + stream.sphere(); + }, + Point: function(object, stream) { + object = object.coordinates; + stream.point(object[0], object[1], object[2]); + }, + MultiPoint: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]); + }, + LineString: function(object, stream) { + streamLine(object.coordinates, stream, 0); + }, + MultiLineString: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamLine(coordinates[i], stream, 0); + }, + Polygon: function(object, stream) { + streamPolygon(object.coordinates, stream); + }, + MultiPolygon: function(object, stream) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) streamPolygon(coordinates[i], stream); + }, + GeometryCollection: function(object, stream) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) streamGeometry(geometries[i], stream); + } +}; + +function streamLine(coordinates, stream, closed) { + var i = -1, n = coordinates.length - closed, coordinate; + stream.lineStart(); + while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]); + stream.lineEnd(); +} + +function streamPolygon(coordinates, stream) { + var i = -1, n = coordinates.length; + stream.polygonStart(); + while (++i < n) streamLine(coordinates[i], stream, 1); + stream.polygonEnd(); +} + +var geoStream = function(object, stream) { + if (object && streamObjectType.hasOwnProperty(object.type)) { + streamObjectType[object.type](object, stream); + } else { + streamGeometry(object, stream); + } +}; + +var areaRingSum = adder(); + +var areaSum = adder(); +var lambda00; +var phi00; +var lambda0; +var cosPhi0; +var sinPhi0; + +var areaStream = { + point: noop, + lineStart: noop, + lineEnd: noop, + polygonStart: function() { + areaRingSum.reset(); + areaStream.lineStart = areaRingStart; + areaStream.lineEnd = areaRingEnd; + }, + polygonEnd: function() { + var areaRing = +areaRingSum; + areaSum.add(areaRing < 0 ? tau + areaRing : areaRing); + this.lineStart = this.lineEnd = this.point = noop; + }, + sphere: function() { + areaSum.add(tau); + } +}; + +function areaRingStart() { + areaStream.point = areaPointFirst; +} + +function areaRingEnd() { + areaPoint(lambda00, phi00); +} + +function areaPointFirst(lambda, phi) { + areaStream.point = areaPoint; + lambda00 = lambda, phi00 = phi; + lambda *= radians, phi *= radians; + lambda0 = lambda, cosPhi0 = cos(phi = phi / 2 + quarterPi), sinPhi0 = sin(phi); +} + +function areaPoint(lambda, phi) { + lambda *= radians, phi *= radians; + phi = phi / 2 + quarterPi; // half the angular distance from south pole + + // Spherical excess E for a spherical triangle with vertices: south pole, + // previous point, current point. Uses a formula derived from Cagnoli’s + // theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2). + var dLambda = lambda - lambda0, + sdLambda = dLambda >= 0 ? 1 : -1, + adLambda = sdLambda * dLambda, + cosPhi = cos(phi), + sinPhi = sin(phi), + k = sinPhi0 * sinPhi, + u = cosPhi0 * cosPhi + k * cos(adLambda), + v = k * sdLambda * sin(adLambda); + areaRingSum.add(atan2(v, u)); + + // Advance the previous points. + lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi; +} + +var area = function(object) { + areaSum.reset(); + geoStream(object, areaStream); + return areaSum * 2; +}; + +function spherical(cartesian) { + return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])]; +} + +function cartesian(spherical) { + var lambda = spherical[0], phi = spherical[1], cosPhi = cos(phi); + return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)]; +} + +function cartesianDot(a, b) { + return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; +} + +function cartesianCross(a, b) { + return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]]; +} + +// TODO return a +function cartesianAddInPlace(a, b) { + a[0] += b[0], a[1] += b[1], a[2] += b[2]; +} + +function cartesianScale(vector, k) { + return [vector[0] * k, vector[1] * k, vector[2] * k]; +} + +// TODO return d +function cartesianNormalizeInPlace(d) { + var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]); + d[0] /= l, d[1] /= l, d[2] /= l; +} + +var lambda0$1; +var phi0; +var lambda1; +var phi1; +var lambda2; +var lambda00$1; +var phi00$1; +var p0; +var deltaSum = adder(); +var ranges; +var range$1; + +var boundsStream = { + point: boundsPoint, + lineStart: boundsLineStart, + lineEnd: boundsLineEnd, + polygonStart: function() { + boundsStream.point = boundsRingPoint; + boundsStream.lineStart = boundsRingStart; + boundsStream.lineEnd = boundsRingEnd; + deltaSum.reset(); + areaStream.polygonStart(); + }, + polygonEnd: function() { + areaStream.polygonEnd(); + boundsStream.point = boundsPoint; + boundsStream.lineStart = boundsLineStart; + boundsStream.lineEnd = boundsLineEnd; + if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90); + else if (deltaSum > epsilon) phi1 = 90; + else if (deltaSum < -epsilon) phi0 = -90; + range$1[0] = lambda0$1, range$1[1] = lambda1; + } +}; + +function boundsPoint(lambda, phi) { + ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]); + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; +} + +function linePoint(lambda, phi) { + var p = cartesian([lambda * radians, phi * radians]); + if (p0) { + var normal = cartesianCross(p0, p), + equatorial = [normal[1], -normal[0], 0], + inflection = cartesianCross(equatorial, normal); + cartesianNormalizeInPlace(inflection); + inflection = spherical(inflection); + var delta = lambda - lambda2, + sign$$1 = delta > 0 ? 1 : -1, + lambdai = inflection[0] * degrees * sign$$1, + phii, + antimeridian = abs(delta) > 180; + if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = inflection[1] * degrees; + if (phii > phi1) phi1 = phii; + } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) { + phii = -inflection[1] * degrees; + if (phii < phi0) phi0 = phii; + } else { + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; + } + if (antimeridian) { + if (lambda < lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } else { + if (lambda1 >= lambda0$1) { + if (lambda < lambda0$1) lambda0$1 = lambda; + if (lambda > lambda1) lambda1 = lambda; + } else { + if (lambda > lambda2) { + if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda; + } else { + if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda; + } + } + } + } else { + ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]); + } + if (phi < phi0) phi0 = phi; + if (phi > phi1) phi1 = phi; + p0 = p, lambda2 = lambda; +} + +function boundsLineStart() { + boundsStream.point = linePoint; +} + +function boundsLineEnd() { + range$1[0] = lambda0$1, range$1[1] = lambda1; + boundsStream.point = boundsPoint; + p0 = null; +} + +function boundsRingPoint(lambda, phi) { + if (p0) { + var delta = lambda - lambda2; + deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); + } else { + lambda00$1 = lambda, phi00$1 = phi; + } + areaStream.point(lambda, phi); + linePoint(lambda, phi); +} + +function boundsRingStart() { + areaStream.lineStart(); +} + +function boundsRingEnd() { + boundsRingPoint(lambda00$1, phi00$1); + areaStream.lineEnd(); + if (abs(deltaSum) > epsilon) lambda0$1 = -(lambda1 = 180); + range$1[0] = lambda0$1, range$1[1] = lambda1; + p0 = null; +} + +// Finds the left-right distance between two longitudes. +// This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want +// the distance between ±180° to be 360°. +function angle(lambda0, lambda1) { + return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; +} + +function rangeCompare(a, b) { + return a[0] - b[0]; +} + +function rangeContains(range$$1, x) { + return range$$1[0] <= range$$1[1] ? range$$1[0] <= x && x <= range$$1[1] : x < range$$1[0] || range$$1[1] < x; +} + +var bounds = function(feature) { + var i, n, a, b, merged, deltaMax, delta; + + phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity); + ranges = []; + geoStream(feature, boundsStream); + + // First, sort ranges by their minimum longitudes. + if (n = ranges.length) { + ranges.sort(rangeCompare); + + // Then, merge any ranges that overlap. + for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { + b = ranges[i]; + if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { + if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; + if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; + } else { + merged.push(a = b); + } + } + + // Finally, find the largest gap between the merged ranges. + // The final bounding box will be the inverse of this gap. + for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { + b = merged[i]; + if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1]; + } + } + + ranges = range$1 = null; + + return lambda0$1 === Infinity || phi0 === Infinity + ? [[NaN, NaN], [NaN, NaN]] + : [[lambda0$1, phi0], [lambda1, phi1]]; +}; + +var W0; +var W1; +var X0; +var Y0; +var Z0; +var X1; +var Y1; +var Z1; +var X2; +var Y2; +var Z2; +var lambda00$2; +var phi00$2; +var x0; +var y0; +var z0; // previous point + +var centroidStream = { + sphere: noop, + point: centroidPoint, + lineStart: centroidLineStart, + lineEnd: centroidLineEnd, + polygonStart: function() { + centroidStream.lineStart = centroidRingStart; + centroidStream.lineEnd = centroidRingEnd; + }, + polygonEnd: function() { + centroidStream.lineStart = centroidLineStart; + centroidStream.lineEnd = centroidLineEnd; + } +}; + +// Arithmetic mean of Cartesian vectors. +function centroidPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos(phi); + centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)); +} + +function centroidPointCartesian(x, y, z) { + ++W0; + X0 += (x - X0) / W0; + Y0 += (y - Y0) / W0; + Z0 += (z - Z0) / W0; +} + +function centroidLineStart() { + centroidStream.point = centroidLinePointFirst; +} + +function centroidLinePointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos(phi); + x0 = cosPhi * cos(lambda); + y0 = cosPhi * sin(lambda); + z0 = sin(phi); + centroidStream.point = centroidLinePoint; + centroidPointCartesian(x0, y0, z0); +} + +function centroidLinePoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos(phi), + x = cosPhi * cos(lambda), + y = cosPhi * sin(lambda), + z = sin(phi), + w = atan2(sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z); + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); +} + +function centroidLineEnd() { + centroidStream.point = centroidPoint; +} + +// See J. E. Brock, The Inertia Tensor for a Spherical Triangle, +// J. Applied Mechanics 42, 239 (1975). +function centroidRingStart() { + centroidStream.point = centroidRingPointFirst; +} + +function centroidRingEnd() { + centroidRingPoint(lambda00$2, phi00$2); + centroidStream.point = centroidPoint; +} + +function centroidRingPointFirst(lambda, phi) { + lambda00$2 = lambda, phi00$2 = phi; + lambda *= radians, phi *= radians; + centroidStream.point = centroidRingPoint; + var cosPhi = cos(phi); + x0 = cosPhi * cos(lambda); + y0 = cosPhi * sin(lambda); + z0 = sin(phi); + centroidPointCartesian(x0, y0, z0); +} + +function centroidRingPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var cosPhi = cos(phi), + x = cosPhi * cos(lambda), + y = cosPhi * sin(lambda), + z = sin(phi), + cx = y0 * z - z0 * y, + cy = z0 * x - x0 * z, + cz = x0 * y - y0 * x, + m = sqrt(cx * cx + cy * cy + cz * cz), + w = asin(m), // line weight = angle + v = m && -w / m; // area weight multiplier + X2 += v * cx; + Y2 += v * cy; + Z2 += v * cz; + W1 += w; + X1 += w * (x0 + (x0 = x)); + Y1 += w * (y0 + (y0 = y)); + Z1 += w * (z0 + (z0 = z)); + centroidPointCartesian(x0, y0, z0); +} + +var centroid = function(object) { + W0 = W1 = + X0 = Y0 = Z0 = + X1 = Y1 = Z1 = + X2 = Y2 = Z2 = 0; + geoStream(object, centroidStream); + + var x = X2, + y = Y2, + z = Z2, + m = x * x + y * y + z * z; + + // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid. + if (m < epsilon2) { + x = X1, y = Y1, z = Z1; + // If the feature has zero length, fall back to arithmetic mean of point vectors. + if (W1 < epsilon) x = X0, y = Y0, z = Z0; + m = x * x + y * y + z * z; + // If the feature still has an undefined ccentroid, then return. + if (m < epsilon2) return [NaN, NaN]; + } + + return [atan2(y, x) * degrees, asin(z / sqrt(m)) * degrees]; +}; + +var constant = function(x) { + return function() { + return x; + }; +}; + +var compose = function(a, b) { + + function compose(x, y) { + return x = a(x, y), b(x[0], x[1]); + } + + if (a.invert && b.invert) compose.invert = function(x, y) { + return x = b.invert(x, y), x && a.invert(x[0], x[1]); + }; + + return compose; +}; + +function rotationIdentity(lambda, phi) { + return [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; +} + +rotationIdentity.invert = rotationIdentity; + +function rotateRadians(deltaLambda, deltaPhi, deltaGamma) { + return (deltaLambda %= tau) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) + : rotationLambda(deltaLambda)) + : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) + : rotationIdentity); +} + +function forwardRotationLambda(deltaLambda) { + return function(lambda, phi) { + return lambda += deltaLambda, [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi]; + }; +} + +function rotationLambda(deltaLambda) { + var rotation = forwardRotationLambda(deltaLambda); + rotation.invert = forwardRotationLambda(-deltaLambda); + return rotation; +} + +function rotationPhiGamma(deltaPhi, deltaGamma) { + var cosDeltaPhi = cos(deltaPhi), + sinDeltaPhi = sin(deltaPhi), + cosDeltaGamma = cos(deltaGamma), + sinDeltaGamma = sin(deltaGamma); + + function rotation(lambda, phi) { + var cosPhi = cos(phi), + x = cos(lambda) * cosPhi, + y = sin(lambda) * cosPhi, + z = sin(phi), + k = z * cosDeltaPhi + x * sinDeltaPhi; + return [ + atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), + asin(k * cosDeltaGamma + y * sinDeltaGamma) + ]; + } + + rotation.invert = function(lambda, phi) { + var cosPhi = cos(phi), + x = cos(lambda) * cosPhi, + y = sin(lambda) * cosPhi, + z = sin(phi), + k = z * cosDeltaGamma - y * sinDeltaGamma; + return [ + atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), + asin(k * cosDeltaPhi - x * sinDeltaPhi) + ]; + }; + + return rotation; +} + +var rotation = function(rotate) { + rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0); + + function forward(coordinates) { + coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates; + } + + forward.invert = function(coordinates) { + coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians); + return coordinates[0] *= degrees, coordinates[1] *= degrees, coordinates; + }; + + return forward; +}; + +// Generates a circle centered at [0°, 0°], with a given radius and precision. +function circleStream(stream, radius, delta, direction, t0, t1) { + if (!delta) return; + var cosRadius = cos(radius), + sinRadius = sin(radius), + step = direction * delta; + if (t0 == null) { + t0 = radius + direction * tau; + t1 = radius - step / 2; + } else { + t0 = circleRadius(cosRadius, t0); + t1 = circleRadius(cosRadius, t1); + if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau; + } + for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { + point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]); + stream.point(point[0], point[1]); + } +} + +// Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. +function circleRadius(cosRadius, point) { + point = cartesian(point), point[0] -= cosRadius; + cartesianNormalizeInPlace(point); + var radius = acos(-point[1]); + return ((-point[2] < 0 ? -radius : radius) + tau - epsilon) % tau; +} + +var circle = function() { + var center = constant([0, 0]), + radius = constant(90), + precision = constant(6), + ring, + rotate, + stream = {point: point}; + + function point(x, y) { + ring.push(x = rotate(x, y)); + x[0] *= degrees, x[1] *= degrees; + } + + function circle() { + var c = center.apply(this, arguments), + r = radius.apply(this, arguments) * radians, + p = precision.apply(this, arguments) * radians; + ring = []; + rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert; + circleStream(stream, r, p, 1); + c = {type: "Polygon", coordinates: [ring]}; + ring = rotate = null; + return c; + } + + circle.center = function(_) { + return arguments.length ? (center = typeof _ === "function" ? _ : constant([+_[0], +_[1]]), circle) : center; + }; + + circle.radius = function(_) { + return arguments.length ? (radius = typeof _ === "function" ? _ : constant(+_), circle) : radius; + }; + + circle.precision = function(_) { + return arguments.length ? (precision = typeof _ === "function" ? _ : constant(+_), circle) : precision; + }; + + return circle; +}; + +var clipBuffer = function() { + var lines = [], + line; + return { + point: function(x, y) { + line.push([x, y]); + }, + lineStart: function() { + lines.push(line = []); + }, + lineEnd: noop, + rejoin: function() { + if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())); + }, + result: function() { + var result = lines; + lines = []; + line = null; + return result; + } + }; +}; + +var pointEqual = function(a, b) { + return abs(a[0] - b[0]) < epsilon && abs(a[1] - b[1]) < epsilon; +}; + +function Intersection(point, points, other, entry) { + this.x = point; + this.z = points; + this.o = other; // another intersection + this.e = entry; // is an entry? + this.v = false; // visited + this.n = this.p = null; // next & previous +} + +// A generalized polygon clipping algorithm: given a polygon that has been cut +// into its visible line segments, and rejoins the segments by interpolating +// along the clip edge. +var clipRejoin = function(segments, compareIntersection, startInside, interpolate, stream) { + var subject = [], + clip = [], + i, + n; + + segments.forEach(function(segment) { + if ((n = segment.length - 1) <= 0) return; + var n, p0 = segment[0], p1 = segment[n], x; + + // If the first and last points of a segment are coincident, then treat as a + // closed ring. TODO if all rings are closed, then the winding order of the + // exterior ring should be checked. + if (pointEqual(p0, p1)) { + stream.lineStart(); + for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]); + stream.lineEnd(); + return; + } + + subject.push(x = new Intersection(p0, segment, null, true)); + clip.push(x.o = new Intersection(p0, null, x, false)); + subject.push(x = new Intersection(p1, segment, null, false)); + clip.push(x.o = new Intersection(p1, null, x, true)); + }); + + if (!subject.length) return; + + clip.sort(compareIntersection); + link(subject); + link(clip); + + for (i = 0, n = clip.length; i < n; ++i) { + clip[i].e = startInside = !startInside; + } + + var start = subject[0], + points, + point; + + while (1) { + // Find first unvisited intersection. + var current = start, + isSubject = true; + while (current.v) if ((current = current.n) === start) return; + points = current.z; + stream.lineStart(); + do { + current.v = current.o.v = true; + if (current.e) { + if (isSubject) { + for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.n.x, 1, stream); + } + current = current.n; + } else { + if (isSubject) { + points = current.p.z; + for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]); + } else { + interpolate(current.x, current.p.x, -1, stream); + } + current = current.p; + } + current = current.o; + points = current.z; + isSubject = !isSubject; + } while (!current.v); + stream.lineEnd(); + } +}; + +function link(array) { + if (!(n = array.length)) return; + var n, + i = 0, + a = array[0], + b; + while (++i < n) { + a.n = b = array[i]; + b.p = a; + a = b; + } + a.n = b = array[0]; + b.p = a; +} + +var sum = adder(); + +var polygonContains = function(polygon, point) { + var lambda = point[0], + phi = point[1], + normal = [sin(lambda), -cos(lambda), 0], + angle = 0, + winding = 0; + + sum.reset(); + + for (var i = 0, n = polygon.length; i < n; ++i) { + if (!(m = (ring = polygon[i]).length)) continue; + var ring, + m, + point0 = ring[m - 1], + lambda0 = point0[0], + phi0 = point0[1] / 2 + quarterPi, + sinPhi0 = sin(phi0), + cosPhi0 = cos(phi0); + + for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { + var point1 = ring[j], + lambda1 = point1[0], + phi1 = point1[1] / 2 + quarterPi, + sinPhi1 = sin(phi1), + cosPhi1 = cos(phi1), + delta = lambda1 - lambda0, + sign$$1 = delta >= 0 ? 1 : -1, + absDelta = sign$$1 * delta, + antimeridian = absDelta > pi, + k = sinPhi0 * sinPhi1; + + sum.add(atan2(k * sign$$1 * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta))); + angle += antimeridian ? delta + sign$$1 * tau : delta; + + // Are the longitudes either side of the point’s meridian (lambda), + // and are the latitudes smaller than the parallel (phi)? + if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { + var arc = cartesianCross(cartesian(point0), cartesian(point1)); + cartesianNormalizeInPlace(arc); + var intersection = cartesianCross(normal, arc); + cartesianNormalizeInPlace(intersection); + var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]); + if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { + winding += antimeridian ^ delta >= 0 ? 1 : -1; + } + } + } + } + + // First, determine whether the South pole is inside or outside: + // + // It is inside if: + // * the polygon winds around it in a clockwise direction. + // * the polygon does not (cumulatively) wind around it, but has a negative + // (counter-clockwise) area. + // + // Second, count the (signed) number of times a segment crosses a lambda + // from the point to the South pole. If it is zero, then the point is the + // same side as the South pole. + + return (angle < -epsilon || angle < epsilon && sum < -epsilon) ^ (winding & 1); +}; + +var clip = function(pointVisible, clipLine, interpolate, start) { + return function(sink) { + var line = clipLine(sink), + ringBuffer = clipBuffer(), + ringSink = clipLine(ringBuffer), + polygonStarted = false, + polygon, + segments, + ring; + + var clip = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { + clip.point = pointRing; + clip.lineStart = ringStart; + clip.lineEnd = ringEnd; + segments = []; + polygon = []; + }, + polygonEnd: function() { + clip.point = point; + clip.lineStart = lineStart; + clip.lineEnd = lineEnd; + segments = d3Array.merge(segments); + var startInside = polygonContains(polygon, start); + if (segments.length) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + clipRejoin(segments, compareIntersection, startInside, interpolate, sink); + } else if (startInside) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + } + if (polygonStarted) sink.polygonEnd(), polygonStarted = false; + segments = polygon = null; + }, + sphere: function() { + sink.polygonStart(); + sink.lineStart(); + interpolate(null, null, 1, sink); + sink.lineEnd(); + sink.polygonEnd(); + } + }; + + function point(lambda, phi) { + if (pointVisible(lambda, phi)) sink.point(lambda, phi); + } + + function pointLine(lambda, phi) { + line.point(lambda, phi); + } + + function lineStart() { + clip.point = pointLine; + line.lineStart(); + } + + function lineEnd() { + clip.point = point; + line.lineEnd(); + } + + function pointRing(lambda, phi) { + ring.push([lambda, phi]); + ringSink.point(lambda, phi); + } + + function ringStart() { + ringSink.lineStart(); + ring = []; + } + + function ringEnd() { + pointRing(ring[0][0], ring[0][1]); + ringSink.lineEnd(); + + var clean = ringSink.clean(), + ringSegments = ringBuffer.result(), + i, n = ringSegments.length, m, + segment, + point; + + ring.pop(); + polygon.push(ring); + ring = null; + + if (!n) return; + + // No intersections. + if (clean & 1) { + segment = ringSegments[0]; + if ((m = segment.length - 1) > 0) { + if (!polygonStarted) sink.polygonStart(), polygonStarted = true; + sink.lineStart(); + for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]); + sink.lineEnd(); + } + return; + } + + // Rejoin connected segments. + // TODO reuse ringBuffer.rejoin()? + if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())); + + segments.push(ringSegments.filter(validSegment)); + } + + return clip; + }; +}; + +function validSegment(segment) { + return segment.length > 1; +} + +// Intersections are sorted along the clip edge. For both antimeridian cutting +// and circle clipping, the same comparison is used. +function compareIntersection(a, b) { + return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon : halfPi - a[1]) + - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon : halfPi - b[1]); +} + +var clipAntimeridian = clip( + function() { return true; }, + clipAntimeridianLine, + clipAntimeridianInterpolate, + [-pi, -halfPi] +); + +// Takes a line and cuts into visible segments. Return values: 0 - there were +// intersections or the line was empty; 1 - no intersections; 2 - there were +// intersections, and the first and last segments should be rejoined. +function clipAntimeridianLine(stream) { + var lambda0 = NaN, + phi0 = NaN, + sign0 = NaN, + clean; // no intersections + + return { + lineStart: function() { + stream.lineStart(); + clean = 1; + }, + point: function(lambda1, phi1) { + var sign1 = lambda1 > 0 ? pi : -pi, + delta = abs(lambda1 - lambda0); + if (abs(delta - pi) < epsilon) { // line crosses a pole + stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + stream.point(lambda1, phi0); + clean = 0; + } else if (sign0 !== sign1 && delta >= pi) { // line crosses antimeridian + if (abs(lambda0 - sign0) < epsilon) lambda0 -= sign0 * epsilon; // handle degeneracies + if (abs(lambda1 - sign1) < epsilon) lambda1 -= sign1 * epsilon; + phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1); + stream.point(sign0, phi0); + stream.lineEnd(); + stream.lineStart(); + stream.point(sign1, phi0); + clean = 0; + } + stream.point(lambda0 = lambda1, phi0 = phi1); + sign0 = sign1; + }, + lineEnd: function() { + stream.lineEnd(); + lambda0 = phi0 = NaN; + }, + clean: function() { + return 2 - clean; // if intersections, rejoin first and last segments + } + }; +} + +function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) { + var cosPhi0, + cosPhi1, + sinLambda0Lambda1 = sin(lambda0 - lambda1); + return abs(sinLambda0Lambda1) > epsilon + ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) + - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) + / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) + : (phi0 + phi1) / 2; +} + +function clipAntimeridianInterpolate(from, to, direction, stream) { + var phi; + if (from == null) { + phi = direction * halfPi; + stream.point(-pi, phi); + stream.point(0, phi); + stream.point(pi, phi); + stream.point(pi, 0); + stream.point(pi, -phi); + stream.point(0, -phi); + stream.point(-pi, -phi); + stream.point(-pi, 0); + stream.point(-pi, phi); + } else if (abs(from[0] - to[0]) > epsilon) { + var lambda = from[0] < to[0] ? pi : -pi; + phi = direction * lambda / 2; + stream.point(-lambda, phi); + stream.point(0, phi); + stream.point(lambda, phi); + } else { + stream.point(to[0], to[1]); + } +} + +var clipCircle = function(radius) { + var cr = cos(radius), + delta = 6 * radians, + smallRadius = cr > 0, + notHemisphere = abs(cr) > epsilon; // TODO optimise for this common case + + function interpolate(from, to, direction, stream) { + circleStream(stream, radius, delta, direction, from, to); + } + + function visible(lambda, phi) { + return cos(lambda) * cos(phi) > cr; + } + + // Takes a line and cuts into visible segments. Return values used for polygon + // clipping: 0 - there were intersections or the line was empty; 1 - no + // intersections 2 - there were intersections, and the first and last segments + // should be rejoined. + function clipLine(stream) { + var point0, // previous point + c0, // code for previous point + v0, // visibility of previous point + v00, // visibility of first point + clean; // no intersections + return { + lineStart: function() { + v00 = v0 = false; + clean = 1; + }, + point: function(lambda, phi) { + var point1 = [lambda, phi], + point2, + v = visible(lambda, phi), + c = smallRadius + ? v ? 0 : code(lambda, phi) + : v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0; + if (!point0 && (v00 = v0 = v)) stream.lineStart(); + // Handle degeneracies. + // TODO ignore if not clipping polygons. + if (v !== v0) { + point2 = intersect(point0, point1); + if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) { + point1[0] += epsilon; + point1[1] += epsilon; + v = visible(point1[0], point1[1]); + } + } + if (v !== v0) { + clean = 0; + if (v) { + // outside going in + stream.lineStart(); + point2 = intersect(point1, point0); + stream.point(point2[0], point2[1]); + } else { + // inside going out + point2 = intersect(point0, point1); + stream.point(point2[0], point2[1]); + stream.lineEnd(); + } + point0 = point2; + } else if (notHemisphere && point0 && smallRadius ^ v) { + var t; + // If the codes for two points are different, or are both zero, + // and there this segment intersects with the small circle. + if (!(c & c0) && (t = intersect(point1, point0, true))) { + clean = 0; + if (smallRadius) { + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + } else { + stream.point(t[1][0], t[1][1]); + stream.lineEnd(); + stream.lineStart(); + stream.point(t[0][0], t[0][1]); + } + } + } + if (v && (!point0 || !pointEqual(point0, point1))) { + stream.point(point1[0], point1[1]); + } + point0 = point1, v0 = v, c0 = c; + }, + lineEnd: function() { + if (v0) stream.lineEnd(); + point0 = null; + }, + // Rejoin first and last segments if there were intersections and the first + // and last points were visible. + clean: function() { + return clean | ((v00 && v0) << 1); + } + }; + } + + // Intersects the great circle between a and b with the clip circle. + function intersect(a, b, two) { + var pa = cartesian(a), + pb = cartesian(b); + + // We have two planes, n1.p = d1 and n2.p = d2. + // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). + var n1 = [1, 0, 0], // normal + n2 = cartesianCross(pa, pb), + n2n2 = cartesianDot(n2, n2), + n1n2 = n2[0], // cartesianDot(n1, n2), + determinant = n2n2 - n1n2 * n1n2; + + // Two polar points. + if (!determinant) return !two && a; + + var c1 = cr * n2n2 / determinant, + c2 = -cr * n1n2 / determinant, + n1xn2 = cartesianCross(n1, n2), + A = cartesianScale(n1, c1), + B = cartesianScale(n2, c2); + cartesianAddInPlace(A, B); + + // Solve |p(t)|^2 = 1. + var u = n1xn2, + w = cartesianDot(A, u), + uu = cartesianDot(u, u), + t2 = w * w - uu * (cartesianDot(A, A) - 1); + + if (t2 < 0) return; + + var t = sqrt(t2), + q = cartesianScale(u, (-w - t) / uu); + cartesianAddInPlace(q, A); + q = spherical(q); + + if (!two) return q; + + // Two intersection points. + var lambda0 = a[0], + lambda1 = b[0], + phi0 = a[1], + phi1 = b[1], + z; + + if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z; + + var delta = lambda1 - lambda0, + polar = abs(delta - pi) < epsilon, + meridian = polar || delta < epsilon; + + if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; + + // Check that the first point is between a and b. + if (meridian + ? polar + ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon ? phi0 : phi1) + : phi0 <= q[1] && q[1] <= phi1 + : delta > pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) { + var q1 = cartesianScale(u, (-w + t) / uu); + cartesianAddInPlace(q1, A); + return [q, spherical(q1)]; + } + } + + // Generates a 4-bit vector representing the location of a point relative to + // the small circle's bounding box. + function code(lambda, phi) { + var r = smallRadius ? radius : pi - radius, + code = 0; + if (lambda < -r) code |= 1; // left + else if (lambda > r) code |= 2; // right + if (phi < -r) code |= 4; // below + else if (phi > r) code |= 8; // above + return code; + } + + return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]); +}; + +var clipLine = function(a, b, x0, y0, x1, y1) { + var ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; + + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy; + if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy; + return true; +}; + +var clipMax = 1e9; +var clipMin = -clipMax; + +// TODO Use d3-polygon’s polygonContains here for the ring check? +// TODO Eliminate duplicate buffering in clipBuffer and polygon.push? + +function clipRectangle(x0, y0, x1, y1) { + + function visible(x, y) { + return x0 <= x && x <= x1 && y0 <= y && y <= y1; + } + + function interpolate(from, to, direction, stream) { + var a = 0, a1 = 0; + if (from == null + || (a = corner(from, direction)) !== (a1 = corner(to, direction)) + || comparePoint(from, to) < 0 ^ direction > 0) { + do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0); + while ((a = (a + direction + 4) % 4) !== a1); + } else { + stream.point(to[0], to[1]); + } + } + + function corner(p, direction) { + return abs(p[0] - x0) < epsilon ? direction > 0 ? 0 : 3 + : abs(p[0] - x1) < epsilon ? direction > 0 ? 2 : 1 + : abs(p[1] - y0) < epsilon ? direction > 0 ? 1 : 0 + : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon + } + + function compareIntersection(a, b) { + return comparePoint(a.x, b.x); + } + + function comparePoint(a, b) { + var ca = corner(a, 1), + cb = corner(b, 1); + return ca !== cb ? ca - cb + : ca === 0 ? b[1] - a[1] + : ca === 1 ? a[0] - b[0] + : ca === 2 ? a[1] - b[1] + : b[0] - a[0]; + } + + return function(stream) { + var activeStream = stream, + bufferStream = clipBuffer(), + segments, + polygon, + ring, + x__, y__, v__, // first point + x_, y_, v_, // previous point + first, + clean; + + var clipStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: polygonStart, + polygonEnd: polygonEnd + }; + + function point(x, y) { + if (visible(x, y)) activeStream.point(x, y); + } + + function polygonInside() { + var winding = 0; + + for (var i = 0, n = polygon.length; i < n; ++i) { + for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { + a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1]; + if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; } + else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; } + } + } + + return winding; + } + + // Buffer geometry within a polygon and then clip it en masse. + function polygonStart() { + activeStream = bufferStream, segments = [], polygon = [], clean = true; + } + + function polygonEnd() { + var startInside = polygonInside(), + cleanInside = clean && startInside, + visible = (segments = d3Array.merge(segments)).length; + if (cleanInside || visible) { + stream.polygonStart(); + if (cleanInside) { + stream.lineStart(); + interpolate(null, null, 1, stream); + stream.lineEnd(); + } + if (visible) { + clipRejoin(segments, compareIntersection, startInside, interpolate, stream); + } + stream.polygonEnd(); + } + activeStream = stream, segments = polygon = ring = null; + } + + function lineStart() { + clipStream.point = linePoint; + if (polygon) polygon.push(ring = []); + first = true; + v_ = false; + x_ = y_ = NaN; + } + + // TODO rather than special-case polygons, simply handle them separately. + // Ideally, coincident intersection points should be jittered to avoid + // clipping issues. + function lineEnd() { + if (segments) { + linePoint(x__, y__); + if (v__ && v_) bufferStream.rejoin(); + segments.push(bufferStream.result()); + } + clipStream.point = point; + if (v_) activeStream.lineEnd(); + } + + function linePoint(x, y) { + var v = visible(x, y); + if (polygon) ring.push([x, y]); + if (first) { + x__ = x, y__ = y, v__ = v; + first = false; + if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + } + } else { + if (v && v_) activeStream.point(x, y); + else { + var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], + b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))]; + if (clipLine(a, b, x0, y0, x1, y1)) { + if (!v_) { + activeStream.lineStart(); + activeStream.point(a[0], a[1]); + } + activeStream.point(b[0], b[1]); + if (!v) activeStream.lineEnd(); + clean = false; + } else if (v) { + activeStream.lineStart(); + activeStream.point(x, y); + clean = false; + } + } + } + x_ = x, y_ = y, v_ = v; + } + + return clipStream; + }; +} + +var extent = function() { + var x0 = 0, + y0 = 0, + x1 = 960, + y1 = 500, + cache, + cacheStream, + clip; + + return clip = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = clipRectangle(x0, y0, x1, y1)(cacheStream = stream); + }, + extent: function(_) { + return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]]; + } + }; +}; + +var lengthSum = adder(); +var lambda0$2; +var sinPhi0$1; +var cosPhi0$1; + +var lengthStream = { + sphere: noop, + point: noop, + lineStart: lengthLineStart, + lineEnd: noop, + polygonStart: noop, + polygonEnd: noop +}; + +function lengthLineStart() { + lengthStream.point = lengthPointFirst; + lengthStream.lineEnd = lengthLineEnd; +} + +function lengthLineEnd() { + lengthStream.point = lengthStream.lineEnd = noop; +} + +function lengthPointFirst(lambda, phi) { + lambda *= radians, phi *= radians; + lambda0$2 = lambda, sinPhi0$1 = sin(phi), cosPhi0$1 = cos(phi); + lengthStream.point = lengthPoint; +} + +function lengthPoint(lambda, phi) { + lambda *= radians, phi *= radians; + var sinPhi = sin(phi), + cosPhi = cos(phi), + delta = abs(lambda - lambda0$2), + cosDelta = cos(delta), + sinDelta = sin(delta), + x = cosPhi * sinDelta, + y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta, + z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta; + lengthSum.add(atan2(sqrt(x * x + y * y), z)); + lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi; +} + +var length = function(object) { + lengthSum.reset(); + geoStream(object, lengthStream); + return +lengthSum; +}; + +var coordinates = [null, null]; +var object = {type: "LineString", coordinates: coordinates}; + +var distance = function(a, b) { + coordinates[0] = a; + coordinates[1] = b; + return length(object); +}; + +var containsObjectType = { + Feature: function(object, point) { + return containsGeometry(object.geometry, point); + }, + FeatureCollection: function(object, point) { + var features = object.features, i = -1, n = features.length; + while (++i < n) if (containsGeometry(features[i].geometry, point)) return true; + return false; + } +}; + +var containsGeometryType = { + Sphere: function() { + return true; + }, + Point: function(object, point) { + return containsPoint(object.coordinates, point); + }, + MultiPoint: function(object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) if (containsPoint(coordinates[i], point)) return true; + return false; + }, + LineString: function(object, point) { + return containsLine(object.coordinates, point); + }, + MultiLineString: function(object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) if (containsLine(coordinates[i], point)) return true; + return false; + }, + Polygon: function(object, point) { + return containsPolygon(object.coordinates, point); + }, + MultiPolygon: function(object, point) { + var coordinates = object.coordinates, i = -1, n = coordinates.length; + while (++i < n) if (containsPolygon(coordinates[i], point)) return true; + return false; + }, + GeometryCollection: function(object, point) { + var geometries = object.geometries, i = -1, n = geometries.length; + while (++i < n) if (containsGeometry(geometries[i], point)) return true; + return false; + } +}; + +function containsGeometry(geometry, point) { + return geometry && containsGeometryType.hasOwnProperty(geometry.type) + ? containsGeometryType[geometry.type](geometry, point) + : false; +} + +function containsPoint(coordinates, point) { + return distance(coordinates, point) === 0; +} + +function containsLine(coordinates, point) { + var ab = distance(coordinates[0], coordinates[1]), + ao = distance(coordinates[0], point), + ob = distance(point, coordinates[1]); + return ao + ob <= ab + epsilon; +} + +function containsPolygon(coordinates, point) { + return !!polygonContains(coordinates.map(ringRadians), pointRadians(point)); +} + +function ringRadians(ring) { + return ring = ring.map(pointRadians), ring.pop(), ring; +} + +function pointRadians(point) { + return [point[0] * radians, point[1] * radians]; +} + +var contains = function(object, point) { + return (object && containsObjectType.hasOwnProperty(object.type) + ? containsObjectType[object.type] + : containsGeometry)(object, point); +}; + +function graticuleX(y0, y1, dy) { + var y = d3Array.range(y0, y1 - epsilon, dy).concat(y1); + return function(x) { return y.map(function(y) { return [x, y]; }); }; +} + +function graticuleY(x0, x1, dx) { + var x = d3Array.range(x0, x1 - epsilon, dx).concat(x1); + return function(y) { return x.map(function(x) { return [x, y]; }); }; +} + +function graticule() { + var x1, x0, X1, X0, + y1, y0, Y1, Y0, + dx = 10, dy = dx, DX = 90, DY = 360, + x, y, X, Y, + precision = 2.5; + + function graticule() { + return {type: "MultiLineString", coordinates: lines()}; + } + + function lines() { + return d3Array.range(ceil(X0 / DX) * DX, X1, DX).map(X) + .concat(d3Array.range(ceil(Y0 / DY) * DY, Y1, DY).map(Y)) + .concat(d3Array.range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon; }).map(x)) + .concat(d3Array.range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon; }).map(y)); + } + + graticule.lines = function() { + return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; }); + }; + + graticule.outline = function() { + return { + type: "Polygon", + coordinates: [ + X(X0).concat( + Y(Y1).slice(1), + X(X1).reverse().slice(1), + Y(Y0).reverse().slice(1)) + ] + }; + }; + + graticule.extent = function(_) { + if (!arguments.length) return graticule.extentMinor(); + return graticule.extentMajor(_).extentMinor(_); + }; + + graticule.extentMajor = function(_) { + if (!arguments.length) return [[X0, Y0], [X1, Y1]]; + X0 = +_[0][0], X1 = +_[1][0]; + Y0 = +_[0][1], Y1 = +_[1][1]; + if (X0 > X1) _ = X0, X0 = X1, X1 = _; + if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _; + return graticule.precision(precision); + }; + + graticule.extentMinor = function(_) { + if (!arguments.length) return [[x0, y0], [x1, y1]]; + x0 = +_[0][0], x1 = +_[1][0]; + y0 = +_[0][1], y1 = +_[1][1]; + if (x0 > x1) _ = x0, x0 = x1, x1 = _; + if (y0 > y1) _ = y0, y0 = y1, y1 = _; + return graticule.precision(precision); + }; + + graticule.step = function(_) { + if (!arguments.length) return graticule.stepMinor(); + return graticule.stepMajor(_).stepMinor(_); + }; + + graticule.stepMajor = function(_) { + if (!arguments.length) return [DX, DY]; + DX = +_[0], DY = +_[1]; + return graticule; + }; + + graticule.stepMinor = function(_) { + if (!arguments.length) return [dx, dy]; + dx = +_[0], dy = +_[1]; + return graticule; + }; + + graticule.precision = function(_) { + if (!arguments.length) return precision; + precision = +_; + x = graticuleX(y0, y1, 90); + y = graticuleY(x0, x1, precision); + X = graticuleX(Y0, Y1, 90); + Y = graticuleY(X0, X1, precision); + return graticule; + }; + + return graticule + .extentMajor([[-180, -90 + epsilon], [180, 90 - epsilon]]) + .extentMinor([[-180, -80 - epsilon], [180, 80 + epsilon]]); +} + +function graticule10() { + return graticule()(); +} + +var interpolate = function(a, b) { + var x0 = a[0] * radians, + y0 = a[1] * radians, + x1 = b[0] * radians, + y1 = b[1] * radians, + cy0 = cos(y0), + sy0 = sin(y0), + cy1 = cos(y1), + sy1 = sin(y1), + kx0 = cy0 * cos(x0), + ky0 = cy0 * sin(x0), + kx1 = cy1 * cos(x1), + ky1 = cy1 * sin(x1), + d = 2 * asin(sqrt(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))), + k = sin(d); + + var interpolate = d ? function(t) { + var B = sin(t *= d) / k, + A = sin(d - t) / k, + x = A * kx0 + B * kx1, + y = A * ky0 + B * ky1, + z = A * sy0 + B * sy1; + return [ + atan2(y, x) * degrees, + atan2(z, sqrt(x * x + y * y)) * degrees + ]; + } : function() { + return [x0 * degrees, y0 * degrees]; + }; + + interpolate.distance = d; + + return interpolate; +}; + +var identity = function(x) { + return x; +}; + +var areaSum$1 = adder(); +var areaRingSum$1 = adder(); +var x00; +var y00; +var x0$1; +var y0$1; + +var areaStream$1 = { + point: noop, + lineStart: noop, + lineEnd: noop, + polygonStart: function() { + areaStream$1.lineStart = areaRingStart$1; + areaStream$1.lineEnd = areaRingEnd$1; + }, + polygonEnd: function() { + areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop; + areaSum$1.add(abs(areaRingSum$1)); + areaRingSum$1.reset(); + }, + result: function() { + var area = areaSum$1 / 2; + areaSum$1.reset(); + return area; + } +}; + +function areaRingStart$1() { + areaStream$1.point = areaPointFirst$1; +} + +function areaPointFirst$1(x, y) { + areaStream$1.point = areaPoint$1; + x00 = x0$1 = x, y00 = y0$1 = y; +} + +function areaPoint$1(x, y) { + areaRingSum$1.add(y0$1 * x - x0$1 * y); + x0$1 = x, y0$1 = y; +} + +function areaRingEnd$1() { + areaPoint$1(x00, y00); +} + +var x0$2 = Infinity; +var y0$2 = x0$2; +var x1 = -x0$2; +var y1 = x1; + +var boundsStream$1 = { + point: boundsPoint$1, + lineStart: noop, + lineEnd: noop, + polygonStart: noop, + polygonEnd: noop, + result: function() { + var bounds = [[x0$2, y0$2], [x1, y1]]; + x1 = y1 = -(y0$2 = x0$2 = Infinity); + return bounds; + } +}; + +function boundsPoint$1(x, y) { + if (x < x0$2) x0$2 = x; + if (x > x1) x1 = x; + if (y < y0$2) y0$2 = y; + if (y > y1) y1 = y; +} + +// TODO Enforce positive area for exterior, negative area for interior? + +var X0$1 = 0; +var Y0$1 = 0; +var Z0$1 = 0; +var X1$1 = 0; +var Y1$1 = 0; +var Z1$1 = 0; +var X2$1 = 0; +var Y2$1 = 0; +var Z2$1 = 0; +var x00$1; +var y00$1; +var x0$3; +var y0$3; + +var centroidStream$1 = { + point: centroidPoint$1, + lineStart: centroidLineStart$1, + lineEnd: centroidLineEnd$1, + polygonStart: function() { + centroidStream$1.lineStart = centroidRingStart$1; + centroidStream$1.lineEnd = centroidRingEnd$1; + }, + polygonEnd: function() { + centroidStream$1.point = centroidPoint$1; + centroidStream$1.lineStart = centroidLineStart$1; + centroidStream$1.lineEnd = centroidLineEnd$1; + }, + result: function() { + var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1] + : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1] + : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1] + : [NaN, NaN]; + X0$1 = Y0$1 = Z0$1 = + X1$1 = Y1$1 = Z1$1 = + X2$1 = Y2$1 = Z2$1 = 0; + return centroid; + } +}; + +function centroidPoint$1(x, y) { + X0$1 += x; + Y0$1 += y; + ++Z0$1; +} + +function centroidLineStart$1() { + centroidStream$1.point = centroidPointFirstLine; +} + +function centroidPointFirstLine(x, y) { + centroidStream$1.point = centroidPointLine; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function centroidPointLine(x, y) { + var dx = x - x0$3, dy = y - y0$3, z = sqrt(dx * dx + dy * dy); + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function centroidLineEnd$1() { + centroidStream$1.point = centroidPoint$1; +} + +function centroidRingStart$1() { + centroidStream$1.point = centroidPointFirstRing; +} + +function centroidRingEnd$1() { + centroidPointRing(x00$1, y00$1); +} + +function centroidPointFirstRing(x, y) { + centroidStream$1.point = centroidPointRing; + centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y); +} + +function centroidPointRing(x, y) { + var dx = x - x0$3, + dy = y - y0$3, + z = sqrt(dx * dx + dy * dy); + + X1$1 += z * (x0$3 + x) / 2; + Y1$1 += z * (y0$3 + y) / 2; + Z1$1 += z; + + z = y0$3 * x - x0$3 * y; + X2$1 += z * (x0$3 + x); + Y2$1 += z * (y0$3 + y); + Z2$1 += z * 3; + centroidPoint$1(x0$3 = x, y0$3 = y); +} + +function PathContext(context) { + this._context = context; +} + +PathContext.prototype = { + _radius: 4.5, + pointRadius: function(_) { + return this._radius = _, this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._context.closePath(); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._context.moveTo(x, y); + this._point = 1; + break; + } + case 1: { + this._context.lineTo(x, y); + break; + } + default: { + this._context.moveTo(x + this._radius, y); + this._context.arc(x, y, this._radius, 0, tau); + break; + } + } + }, + result: noop +}; + +var lengthSum$1 = adder(); +var lengthRing; +var x00$2; +var y00$2; +var x0$4; +var y0$4; + +var lengthStream$1 = { + point: noop, + lineStart: function() { + lengthStream$1.point = lengthPointFirst$1; + }, + lineEnd: function() { + if (lengthRing) lengthPoint$1(x00$2, y00$2); + lengthStream$1.point = noop; + }, + polygonStart: function() { + lengthRing = true; + }, + polygonEnd: function() { + lengthRing = null; + }, + result: function() { + var length = +lengthSum$1; + lengthSum$1.reset(); + return length; + } +}; + +function lengthPointFirst$1(x, y) { + lengthStream$1.point = lengthPoint$1; + x00$2 = x0$4 = x, y00$2 = y0$4 = y; +} + +function lengthPoint$1(x, y) { + x0$4 -= x, y0$4 -= y; + lengthSum$1.add(sqrt(x0$4 * x0$4 + y0$4 * y0$4)); + x0$4 = x, y0$4 = y; +} + +function PathString() { + this._string = []; +} + +PathString.prototype = { + _radius: 4.5, + _circle: circle$1(4.5), + pointRadius: function(_) { + if ((_ = +_) !== this._radius) this._radius = _, this._circle = null; + return this; + }, + polygonStart: function() { + this._line = 0; + }, + polygonEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line === 0) this._string.push("Z"); + this._point = NaN; + }, + point: function(x, y) { + switch (this._point) { + case 0: { + this._string.push("M", x, ",", y); + this._point = 1; + break; + } + case 1: { + this._string.push("L", x, ",", y); + break; + } + default: { + if (this._circle == null) this._circle = circle$1(this._radius); + this._string.push("M", x, ",", y, this._circle); + break; + } + } + }, + result: function() { + if (this._string.length) { + var result = this._string.join(""); + this._string = []; + return result; + } else { + return null; + } + } +}; + +function circle$1(radius) { + return "m0," + radius + + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + + "z"; +} + +var index = function(projection, context) { + var pointRadius = 4.5, + projectionStream, + contextStream; + + function path(object) { + if (object) { + if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments)); + geoStream(object, projectionStream(contextStream)); + } + return contextStream.result(); + } + + path.area = function(object) { + geoStream(object, projectionStream(areaStream$1)); + return areaStream$1.result(); + }; + + path.measure = function(object) { + geoStream(object, projectionStream(lengthStream$1)); + return lengthStream$1.result(); + }; + + path.bounds = function(object) { + geoStream(object, projectionStream(boundsStream$1)); + return boundsStream$1.result(); + }; + + path.centroid = function(object) { + geoStream(object, projectionStream(centroidStream$1)); + return centroidStream$1.result(); + }; + + path.projection = function(_) { + return arguments.length ? (projectionStream = _ == null ? (projection = null, identity) : (projection = _).stream, path) : projection; + }; + + path.context = function(_) { + if (!arguments.length) return context; + contextStream = _ == null ? (context = null, new PathString) : new PathContext(context = _); + if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius); + return path; + }; + + path.pointRadius = function(_) { + if (!arguments.length) return pointRadius; + pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_); + return path; + }; + + return path.projection(projection).context(context); +}; + +var transform = function(methods) { + return { + stream: transformer(methods) + }; +}; + +function transformer(methods) { + return function(stream) { + var s = new TransformStream; + for (var key in methods) s[key] = methods[key]; + s.stream = stream; + return s; + }; +} + +function TransformStream() {} + +TransformStream.prototype = { + constructor: TransformStream, + point: function(x, y) { this.stream.point(x, y); }, + sphere: function() { this.stream.sphere(); }, + lineStart: function() { this.stream.lineStart(); }, + lineEnd: function() { this.stream.lineEnd(); }, + polygonStart: function() { this.stream.polygonStart(); }, + polygonEnd: function() { this.stream.polygonEnd(); } +}; + +function fit(projection, fitBounds, object) { + var clip = projection.clipExtent && projection.clipExtent(); + projection.scale(150).translate([0, 0]); + if (clip != null) projection.clipExtent(null); + geoStream(object, projection.stream(boundsStream$1)); + fitBounds(boundsStream$1.result()); + if (clip != null) projection.clipExtent(clip); + return projection; +} + +function fitExtent(projection, extent, object) { + return fit(projection, function(b) { + var w = extent[1][0] - extent[0][0], + h = extent[1][1] - extent[0][1], + k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), + x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, + y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2; + projection.scale(150 * k).translate([x, y]); + }, object); +} + +function fitSize(projection, size, object) { + return fitExtent(projection, [[0, 0], size], object); +} + +function fitWidth(projection, width, object) { + return fit(projection, function(b) { + var w = +width, + k = w / (b[1][0] - b[0][0]), + x = (w - k * (b[1][0] + b[0][0])) / 2, + y = -k * b[0][1]; + projection.scale(150 * k).translate([x, y]); + }, object); +} + +function fitHeight(projection, height, object) { + return fit(projection, function(b) { + var h = +height, + k = h / (b[1][1] - b[0][1]), + x = -k * b[0][0], + y = (h - k * (b[1][1] + b[0][1])) / 2; + projection.scale(150 * k).translate([x, y]); + }, object); +} + +var maxDepth = 16; +var cosMinDistance = cos(30 * radians); // cos(minimum angular distance) + +var resample = function(project, delta2) { + return +delta2 ? resample$1(project, delta2) : resampleNone(project); +}; + +function resampleNone(project) { + return transformer({ + point: function(x, y) { + x = project(x, y); + this.stream.point(x[0], x[1]); + } + }); +} + +function resample$1(project, delta2) { + + function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { + var dx = x1 - x0, + dy = y1 - y0, + d2 = dx * dx + dy * dy; + if (d2 > 4 * delta2 && depth--) { + var a = a0 + a1, + b = b0 + b1, + c = c0 + c1, + m = sqrt(a * a + b * b + c * c), + phi2 = asin(c /= m), + lambda2 = abs(abs(c) - 1) < epsilon || abs(lambda0 - lambda1) < epsilon ? (lambda0 + lambda1) / 2 : atan2(b, a), + p = project(lambda2, phi2), + x2 = p[0], + y2 = p[1], + dx2 = x2 - x0, + dy2 = y2 - y0, + dz = dy * dx2 - dx * dy2; + if (dz * dz / d2 > delta2 // perpendicular projected distance + || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end + || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream); + stream.point(x2, y2); + resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream); + } + } + } + return function(stream) { + var lambda00, x00, y00, a00, b00, c00, // first point + lambda0, x0, y0, a0, b0, c0; // previous point + + var resampleStream = { + point: point, + lineStart: lineStart, + lineEnd: lineEnd, + polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; }, + polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; } + }; + + function point(x, y) { + x = project(x, y); + stream.point(x[0], x[1]); + } + + function lineStart() { + x0 = NaN; + resampleStream.point = linePoint; + stream.lineStart(); + } + + function linePoint(lambda, phi) { + var c = cartesian([lambda, phi]), p = project(lambda, phi); + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream); + stream.point(x0, y0); + } + + function lineEnd() { + resampleStream.point = point; + stream.lineEnd(); + } + + function ringStart() { + lineStart(); + resampleStream.point = ringPoint; + resampleStream.lineEnd = ringEnd; + } + + function ringPoint(lambda, phi) { + linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0; + resampleStream.point = linePoint; + } + + function ringEnd() { + resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream); + resampleStream.lineEnd = lineEnd; + lineEnd(); + } + + return resampleStream; + }; +} + +var transformRadians = transformer({ + point: function(x, y) { + this.stream.point(x * radians, y * radians); + } +}); + +function transformRotate(rotate) { + return transformer({ + point: function(x, y) { + var r = rotate(x, y); + return this.stream.point(r[0], r[1]); + } + }); +} + +function projection(project) { + return projectionMutator(function() { return project; })(); +} + +function projectionMutator(projectAt) { + var project, + k = 150, // scale + x = 480, y = 250, // translate + dx, dy, lambda = 0, phi = 0, // center + deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate + theta = null, preclip = clipAntimeridian, // clip angle + x0 = null, y0, x1, y1, postclip = identity, // clip extent + delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision + cache, + cacheStream; + + function projection(point) { + point = projectRotate(point[0] * radians, point[1] * radians); + return [point[0] * k + dx, dy - point[1] * k]; + } + + function invert(point) { + point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k); + return point && [point[0] * degrees, point[1] * degrees]; + } + + function projectTransform(x, y) { + return x = project(x, y), [x[0] * k + dx, dy - x[1] * k]; + } + + projection.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream))))); + }; + + projection.preclip = function(_) { + return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip; + }; + + projection.postclip = function(_) { + return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip; + }; + + projection.clipAngle = function(_) { + return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees; + }; + + projection.clipExtent = function(_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + projection.scale = function(_) { + return arguments.length ? (k = +_, recenter()) : k; + }; + + projection.translate = function(_) { + return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y]; + }; + + projection.center = function(_) { + return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees, phi * degrees]; + }; + + projection.rotate = function(_) { + return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees, deltaPhi * degrees, deltaGamma * degrees]; + }; + + projection.precision = function(_) { + return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2); + }; + + projection.fitExtent = function(extent, object) { + return fitExtent(projection, extent, object); + }; + + projection.fitSize = function(size, object) { + return fitSize(projection, size, object); + }; + + projection.fitWidth = function(width, object) { + return fitWidth(projection, width, object); + }; + + projection.fitHeight = function(height, object) { + return fitHeight(projection, height, object); + }; + + function recenter() { + projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project); + var center = project(lambda, phi); + dx = x - center[0] * k; + dy = y + center[1] * k; + return reset(); + } + + function reset() { + cache = cacheStream = null; + return projection; + } + + return function() { + project = projectAt.apply(this, arguments); + projection.invert = project.invert && invert; + return recenter(); + }; +} + +function conicProjection(projectAt) { + var phi0 = 0, + phi1 = pi / 3, + m = projectionMutator(projectAt), + p = m(phi0, phi1); + + p.parallels = function(_) { + return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees, phi1 * degrees]; + }; + + return p; +} + +function cylindricalEqualAreaRaw(phi0) { + var cosPhi0 = cos(phi0); + + function forward(lambda, phi) { + return [lambda * cosPhi0, sin(phi) / cosPhi0]; + } + + forward.invert = function(x, y) { + return [x / cosPhi0, asin(y * cosPhi0)]; + }; + + return forward; +} + +function conicEqualAreaRaw(y0, y1) { + var sy0 = sin(y0), n = (sy0 + sin(y1)) / 2; + + // Are the parallels symmetrical around the Equator? + if (abs(n) < epsilon) return cylindricalEqualAreaRaw(y0); + + var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c) / n; + + function project(x, y) { + var r = sqrt(c - 2 * n * sin(y)) / n; + return [r * sin(x *= n), r0 - r * cos(x)]; + } + + project.invert = function(x, y) { + var r0y = r0 - y; + return [atan2(x, abs(r0y)) / n * sign(r0y), asin((c - (x * x + r0y * r0y) * n * n) / (2 * n))]; + }; + + return project; +} + +var conicEqualArea = function() { + return conicProjection(conicEqualAreaRaw) + .scale(155.424) + .center([0, 33.6442]); +}; + +var albers = function() { + return conicEqualArea() + .parallels([29.5, 45.5]) + .scale(1070) + .translate([480, 250]) + .rotate([96, 0]) + .center([-0.6, 38.7]); +}; + +// The projections must have mutually exclusive clip regions on the sphere, +// as this will avoid emitting interleaving lines and polygons. +function multiplex(streams) { + var n = streams.length; + return { + point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); }, + sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); }, + lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); }, + lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); }, + polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); }, + polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); } + }; +} + +// A composite projection for the United States, configured by default for +// 960×500. The projection also works quite well at 960×600 if you change the +// scale to 1285 and adjust the translate accordingly. The set of standard +// parallels for each region comes from USGS, which is published here: +// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers +var albersUsa = function() { + var cache, + cacheStream, + lower48 = albers(), lower48Point, + alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338 + hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007 + point, pointStream = {point: function(x, y) { point = [x, y]; }}; + + function albersUsa(coordinates) { + var x = coordinates[0], y = coordinates[1]; + return point = null, (lower48Point.point(x, y), point) + || (alaskaPoint.point(x, y), point) + || (hawaiiPoint.point(x, y), point); + } + + albersUsa.invert = function(coordinates) { + var k = lower48.scale(), + t = lower48.translate(), + x = (coordinates[0] - t[0]) / k, + y = (coordinates[1] - t[1]) / k; + return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska + : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii + : lower48).invert(coordinates); + }; + + albersUsa.stream = function(stream) { + return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]); + }; + + albersUsa.precision = function(_) { + if (!arguments.length) return lower48.precision(); + lower48.precision(_), alaska.precision(_), hawaii.precision(_); + return reset(); + }; + + albersUsa.scale = function(_) { + if (!arguments.length) return lower48.scale(); + lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_); + return albersUsa.translate(lower48.translate()); + }; + + albersUsa.translate = function(_) { + if (!arguments.length) return lower48.translate(); + var k = lower48.scale(), x = +_[0], y = +_[1]; + + lower48Point = lower48 + .translate(_) + .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]]) + .stream(pointStream); + + alaskaPoint = alaska + .translate([x - 0.307 * k, y + 0.201 * k]) + .clipExtent([[x - 0.425 * k + epsilon, y + 0.120 * k + epsilon], [x - 0.214 * k - epsilon, y + 0.234 * k - epsilon]]) + .stream(pointStream); + + hawaiiPoint = hawaii + .translate([x - 0.205 * k, y + 0.212 * k]) + .clipExtent([[x - 0.214 * k + epsilon, y + 0.166 * k + epsilon], [x - 0.115 * k - epsilon, y + 0.234 * k - epsilon]]) + .stream(pointStream); + + return reset(); + }; + + albersUsa.fitExtent = function(extent, object) { + return fitExtent(albersUsa, extent, object); + }; + + albersUsa.fitSize = function(size, object) { + return fitSize(albersUsa, size, object); + }; + + albersUsa.fitWidth = function(width, object) { + return fitWidth(albersUsa, width, object); + }; + + albersUsa.fitHeight = function(height, object) { + return fitHeight(albersUsa, height, object); + }; + + function reset() { + cache = cacheStream = null; + return albersUsa; + } + + return albersUsa.scale(1070); +}; + +function azimuthalRaw(scale) { + return function(x, y) { + var cx = cos(x), + cy = cos(y), + k = scale(cx * cy); + return [ + k * cy * sin(x), + k * sin(y) + ]; + } +} + +function azimuthalInvert(angle) { + return function(x, y) { + var z = sqrt(x * x + y * y), + c = angle(z), + sc = sin(c), + cc = cos(c); + return [ + atan2(x * sc, z * cc), + asin(z && y * sc / z) + ]; + } +} + +var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) { + return sqrt(2 / (1 + cxcy)); +}); + +azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) { + return 2 * asin(z / 2); +}); + +var azimuthalEqualArea = function() { + return projection(azimuthalEqualAreaRaw) + .scale(124.75) + .clipAngle(180 - 1e-3); +}; + +var azimuthalEquidistantRaw = azimuthalRaw(function(c) { + return (c = acos(c)) && c / sin(c); +}); + +azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) { + return z; +}); + +var azimuthalEquidistant = function() { + return projection(azimuthalEquidistantRaw) + .scale(79.4188) + .clipAngle(180 - 1e-3); +}; + +function mercatorRaw(lambda, phi) { + return [lambda, log(tan((halfPi + phi) / 2))]; +} + +mercatorRaw.invert = function(x, y) { + return [x, 2 * atan(exp(y)) - halfPi]; +}; + +var mercator = function() { + return mercatorProjection(mercatorRaw) + .scale(961 / tau); +}; + +function mercatorProjection(project) { + var m = projection(project), + center = m.center, + scale = m.scale, + translate = m.translate, + clipExtent = m.clipExtent, + x0 = null, y0, x1, y1; // clip extent + + m.scale = function(_) { + return arguments.length ? (scale(_), reclip()) : scale(); + }; + + m.translate = function(_) { + return arguments.length ? (translate(_), reclip()) : translate(); + }; + + m.center = function(_) { + return arguments.length ? (center(_), reclip()) : center(); + }; + + m.clipExtent = function(_) { + return arguments.length ? (_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }; + + function reclip() { + var k = pi * scale(), + t = m(rotation(m.rotate()).invert([0, 0])); + return clipExtent(x0 == null + ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw + ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] + : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]); + } + + return reclip(); +} + +function tany(y) { + return tan((halfPi + y) / 2); +} + +function conicConformalRaw(y0, y1) { + var cy0 = cos(y0), + n = y0 === y1 ? sin(y0) : log(cy0 / cos(y1)) / log(tany(y1) / tany(y0)), + f = cy0 * pow(tany(y0), n) / n; + + if (!n) return mercatorRaw; + + function project(x, y) { + if (f > 0) { if (y < -halfPi + epsilon) y = -halfPi + epsilon; } + else { if (y > halfPi - epsilon) y = halfPi - epsilon; } + var r = f / pow(tany(y), n); + return [r * sin(n * x), f - r * cos(n * x)]; + } + + project.invert = function(x, y) { + var fy = f - y, r = sign(n) * sqrt(x * x + fy * fy); + return [atan2(x, abs(fy)) / n * sign(fy), 2 * atan(pow(f / r, 1 / n)) - halfPi]; + }; + + return project; +} + +var conicConformal = function() { + return conicProjection(conicConformalRaw) + .scale(109.5) + .parallels([30, 30]); +}; + +function equirectangularRaw(lambda, phi) { + return [lambda, phi]; +} + +equirectangularRaw.invert = equirectangularRaw; + +var equirectangular = function() { + return projection(equirectangularRaw) + .scale(152.63); +}; + +function conicEquidistantRaw(y0, y1) { + var cy0 = cos(y0), + n = y0 === y1 ? sin(y0) : (cy0 - cos(y1)) / (y1 - y0), + g = cy0 / n + y0; + + if (abs(n) < epsilon) return equirectangularRaw; + + function project(x, y) { + var gy = g - y, nx = n * x; + return [gy * sin(nx), g - gy * cos(nx)]; + } + + project.invert = function(x, y) { + var gy = g - y; + return [atan2(x, abs(gy)) / n * sign(gy), g - sign(n) * sqrt(x * x + gy * gy)]; + }; + + return project; +} + +var conicEquidistant = function() { + return conicProjection(conicEquidistantRaw) + .scale(131.154) + .center([0, 13.9389]); +}; + +function gnomonicRaw(x, y) { + var cy = cos(y), k = cos(x) * cy; + return [cy * sin(x) / k, sin(y) / k]; +} + +gnomonicRaw.invert = azimuthalInvert(atan); + +var gnomonic = function() { + return projection(gnomonicRaw) + .scale(144.049) + .clipAngle(60); +}; + +function scaleTranslate(kx, ky, tx, ty) { + return kx === 1 && ky === 1 && tx === 0 && ty === 0 ? identity : transformer({ + point: function(x, y) { + this.stream.point(x * kx + tx, y * ky + ty); + } + }); +} + +var identity$1 = function() { + var k = 1, tx = 0, ty = 0, sx = 1, sy = 1, transform$$1 = identity, // scale, translate and reflect + x0 = null, y0, x1, y1, // clip extent + postclip = identity, + cache, + cacheStream, + projection; + + function reset() { + cache = cacheStream = null; + return projection; + } + + return projection = { + stream: function(stream) { + return cache && cacheStream === stream ? cache : cache = transform$$1(postclip(cacheStream = stream)); + }, + postclip: function(_) { + return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip; + }, + clipExtent: function(_) { + return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]]; + }, + scale: function(_) { + return arguments.length ? (transform$$1 = scaleTranslate((k = +_) * sx, k * sy, tx, ty), reset()) : k; + }, + translate: function(_) { + return arguments.length ? (transform$$1 = scaleTranslate(k * sx, k * sy, tx = +_[0], ty = +_[1]), reset()) : [tx, ty]; + }, + reflectX: function(_) { + return arguments.length ? (transform$$1 = scaleTranslate(k * (sx = _ ? -1 : 1), k * sy, tx, ty), reset()) : sx < 0; + }, + reflectY: function(_) { + return arguments.length ? (transform$$1 = scaleTranslate(k * sx, k * (sy = _ ? -1 : 1), tx, ty), reset()) : sy < 0; + }, + fitExtent: function(extent, object) { + return fitExtent(projection, extent, object); + }, + fitSize: function(size, object) { + return fitSize(projection, size, object); + }, + fitWidth: function(width, object) { + return fitWidth(projection, width, object); + }, + fitHeight: function(height, object) { + return fitHeight(projection, height, object); + } + }; +}; + +function naturalEarth1Raw(lambda, phi) { + var phi2 = phi * phi, phi4 = phi2 * phi2; + return [ + lambda * (0.8707 - 0.131979 * phi2 + phi4 * (-0.013791 + phi4 * (0.003971 * phi2 - 0.001529 * phi4))), + phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) + ]; +} + +naturalEarth1Raw.invert = function(x, y) { + var phi = y, i = 25, delta; + do { + var phi2 = phi * phi, phi4 = phi2 * phi2; + phi -= delta = (phi * (1.007226 + phi2 * (0.015085 + phi4 * (-0.044475 + 0.028874 * phi2 - 0.005916 * phi4))) - y) / + (1.007226 + phi2 * (0.015085 * 3 + phi4 * (-0.044475 * 7 + 0.028874 * 9 * phi2 - 0.005916 * 11 * phi4))); + } while (abs(delta) > epsilon && --i > 0); + return [ + x / (0.8707 + (phi2 = phi * phi) * (-0.131979 + phi2 * (-0.013791 + phi2 * phi2 * phi2 * (0.003971 - 0.001529 * phi2)))), + phi + ]; +}; + +var naturalEarth1 = function() { + return projection(naturalEarth1Raw) + .scale(175.295); +}; + +function orthographicRaw(x, y) { + return [cos(y) * sin(x), sin(y)]; +} + +orthographicRaw.invert = azimuthalInvert(asin); + +var orthographic = function() { + return projection(orthographicRaw) + .scale(249.5) + .clipAngle(90 + epsilon); +}; + +function stereographicRaw(x, y) { + var cy = cos(y), k = 1 + cos(x) * cy; + return [cy * sin(x) / k, sin(y) / k]; +} + +stereographicRaw.invert = azimuthalInvert(function(z) { + return 2 * atan(z); +}); + +var stereographic = function() { + return projection(stereographicRaw) + .scale(250) + .clipAngle(142); +}; + +function transverseMercatorRaw(lambda, phi) { + return [log(tan((halfPi + phi) / 2)), -lambda]; +} + +transverseMercatorRaw.invert = function(x, y) { + return [-y, 2 * atan(exp(x)) - halfPi]; +}; + +var transverseMercator = function() { + var m = mercatorProjection(transverseMercatorRaw), + center = m.center, + rotate = m.rotate; + + m.center = function(_) { + return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]); + }; + + m.rotate = function(_) { + return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]); + }; + + return rotate([0, 0, 90]) + .scale(159.155); +}; + +exports.geoArea = area; +exports.geoBounds = bounds; +exports.geoCentroid = centroid; +exports.geoCircle = circle; +exports.geoClipAntimeridian = clipAntimeridian; +exports.geoClipCircle = clipCircle; +exports.geoClipExtent = extent; +exports.geoClipRectangle = clipRectangle; +exports.geoContains = contains; +exports.geoDistance = distance; +exports.geoGraticule = graticule; +exports.geoGraticule10 = graticule10; +exports.geoInterpolate = interpolate; +exports.geoLength = length; +exports.geoPath = index; +exports.geoAlbers = albers; +exports.geoAlbersUsa = albersUsa; +exports.geoAzimuthalEqualArea = azimuthalEqualArea; +exports.geoAzimuthalEqualAreaRaw = azimuthalEqualAreaRaw; +exports.geoAzimuthalEquidistant = azimuthalEquidistant; +exports.geoAzimuthalEquidistantRaw = azimuthalEquidistantRaw; +exports.geoConicConformal = conicConformal; +exports.geoConicConformalRaw = conicConformalRaw; +exports.geoConicEqualArea = conicEqualArea; +exports.geoConicEqualAreaRaw = conicEqualAreaRaw; +exports.geoConicEquidistant = conicEquidistant; +exports.geoConicEquidistantRaw = conicEquidistantRaw; +exports.geoEquirectangular = equirectangular; +exports.geoEquirectangularRaw = equirectangularRaw; +exports.geoGnomonic = gnomonic; +exports.geoGnomonicRaw = gnomonicRaw; +exports.geoIdentity = identity$1; +exports.geoProjection = projection; +exports.geoProjectionMutator = projectionMutator; +exports.geoMercator = mercator; +exports.geoMercatorRaw = mercatorRaw; +exports.geoNaturalEarth1 = naturalEarth1; +exports.geoNaturalEarth1Raw = naturalEarth1Raw; +exports.geoOrthographic = orthographic; +exports.geoOrthographicRaw = orthographicRaw; +exports.geoStereographic = stereographic; +exports.geoStereographicRaw = stereographicRaw; +exports.geoTransverseMercator = transverseMercator; +exports.geoTransverseMercatorRaw = transverseMercatorRaw; +exports.geoRotation = rotation; +exports.geoStream = geoStream; +exports.geoTransform = transform; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-array":23}],36:[function(require,module,exports){ +// https://d3js.org/d3-hierarchy/ Version 1.1.5. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +function defaultSeparation(a, b) { + return a.parent === b.parent ? 1 : 2; +} + +function meanX(children) { + return children.reduce(meanXReduce, 0) / children.length; +} + +function meanXReduce(x, c) { + return x + c.x; +} + +function maxY(children) { + return 1 + children.reduce(maxYReduce, 0); +} + +function maxYReduce(y, c) { + return Math.max(y, c.y); +} + +function leafLeft(node) { + var children; + while (children = node.children) node = children[0]; + return node; +} + +function leafRight(node) { + var children; + while (children = node.children) node = children[children.length - 1]; + return node; +} + +var cluster = function() { + var separation = defaultSeparation, + dx = 1, + dy = 1, + nodeSize = false; + + function cluster(root) { + var previousNode, + x = 0; + + // First walk, computing the initial x & y values. + root.eachAfter(function(node) { + var children = node.children; + if (children) { + node.x = meanX(children); + node.y = maxY(children); + } else { + node.x = previousNode ? x += separation(node, previousNode) : 0; + node.y = 0; + previousNode = node; + } + }); + + var left = leafLeft(root), + right = leafRight(root), + x0 = left.x - separation(left, right) / 2, + x1 = right.x + separation(right, left) / 2; + + // Second walk, normalizing x & y to the desired size. + return root.eachAfter(nodeSize ? function(node) { + node.x = (node.x - root.x) * dx; + node.y = (root.y - node.y) * dy; + } : function(node) { + node.x = (node.x - x0) / (x1 - x0) * dx; + node.y = (1 - (root.y ? node.y / root.y : 1)) * dy; + }); + } + + cluster.separation = function(x) { + return arguments.length ? (separation = x, cluster) : separation; + }; + + cluster.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]); + }; + + cluster.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null); + }; + + return cluster; +}; + +function count(node) { + var sum = 0, + children = node.children, + i = children && children.length; + if (!i) sum = 1; + else while (--i >= 0) sum += children[i].value; + node.value = sum; +} + +var node_count = function() { + return this.eachAfter(count); +}; + +var node_each = function(callback) { + var node = this, current, next = [node], children, i, n; + do { + current = next.reverse(), next = []; + while (node = current.pop()) { + callback(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + next.push(children[i]); + } + } + } while (next.length); + return this; +}; + +var node_eachBefore = function(callback) { + var node = this, nodes = [node], children, i; + while (node = nodes.pop()) { + callback(node), children = node.children; + if (children) for (i = children.length - 1; i >= 0; --i) { + nodes.push(children[i]); + } + } + return this; +}; + +var node_eachAfter = function(callback) { + var node = this, nodes = [node], next = [], children, i, n; + while (node = nodes.pop()) { + next.push(node), children = node.children; + if (children) for (i = 0, n = children.length; i < n; ++i) { + nodes.push(children[i]); + } + } + while (node = next.pop()) { + callback(node); + } + return this; +}; + +var node_sum = function(value) { + return this.eachAfter(function(node) { + var sum = +value(node.data) || 0, + children = node.children, + i = children && children.length; + while (--i >= 0) sum += children[i].value; + node.value = sum; + }); +}; + +var node_sort = function(compare) { + return this.eachBefore(function(node) { + if (node.children) { + node.children.sort(compare); + } + }); +}; + +var node_path = function(end) { + var start = this, + ancestor = leastCommonAncestor(start, end), + nodes = [start]; + while (start !== ancestor) { + start = start.parent; + nodes.push(start); + } + var k = nodes.length; + while (end !== ancestor) { + nodes.splice(k, 0, end); + end = end.parent; + } + return nodes; +}; + +function leastCommonAncestor(a, b) { + if (a === b) return a; + var aNodes = a.ancestors(), + bNodes = b.ancestors(), + c = null; + a = aNodes.pop(); + b = bNodes.pop(); + while (a === b) { + c = a; + a = aNodes.pop(); + b = bNodes.pop(); + } + return c; +} + +var node_ancestors = function() { + var node = this, nodes = [node]; + while (node = node.parent) { + nodes.push(node); + } + return nodes; +}; + +var node_descendants = function() { + var nodes = []; + this.each(function(node) { + nodes.push(node); + }); + return nodes; +}; + +var node_leaves = function() { + var leaves = []; + this.eachBefore(function(node) { + if (!node.children) { + leaves.push(node); + } + }); + return leaves; +}; + +var node_links = function() { + var root = this, links = []; + root.each(function(node) { + if (node !== root) { // Don’t include the root’s parent, if any. + links.push({source: node.parent, target: node}); + } + }); + return links; +}; + +function hierarchy(data, children) { + var root = new Node(data), + valued = +data.value && (root.value = data.value), + node, + nodes = [root], + child, + childs, + i, + n; + + if (children == null) children = defaultChildren; + + while (node = nodes.pop()) { + if (valued) node.value = +node.data.value; + if ((childs = children(node.data)) && (n = childs.length)) { + node.children = new Array(n); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new Node(childs[i])); + child.parent = node; + child.depth = node.depth + 1; + } + } + } + + return root.eachBefore(computeHeight); +} + +function node_copy() { + return hierarchy(this).eachBefore(copyData); +} + +function defaultChildren(d) { + return d.children; +} + +function copyData(node) { + node.data = node.data.data; +} + +function computeHeight(node) { + var height = 0; + do node.height = height; + while ((node = node.parent) && (node.height < ++height)); +} + +function Node(data) { + this.data = data; + this.depth = + this.height = 0; + this.parent = null; +} + +Node.prototype = hierarchy.prototype = { + constructor: Node, + count: node_count, + each: node_each, + eachAfter: node_eachAfter, + eachBefore: node_eachBefore, + sum: node_sum, + sort: node_sort, + path: node_path, + ancestors: node_ancestors, + descendants: node_descendants, + leaves: node_leaves, + links: node_links, + copy: node_copy +}; + +var slice = Array.prototype.slice; + +function shuffle(array) { + var m = array.length, + t, + i; + + while (m) { + i = Math.random() * m-- | 0; + t = array[m]; + array[m] = array[i]; + array[i] = t; + } + + return array; +} + +var enclose = function(circles) { + var i = 0, n = (circles = shuffle(slice.call(circles))).length, B = [], p, e; + + while (i < n) { + p = circles[i]; + if (e && enclosesWeak(e, p)) ++i; + else e = encloseBasis(B = extendBasis(B, p)), i = 0; + } + + return e; +}; + +function extendBasis(B, p) { + var i, j; + + if (enclosesWeakAll(p, B)) return [p]; + + // If we get here then B must have at least one element. + for (i = 0; i < B.length; ++i) { + if (enclosesNot(p, B[i]) + && enclosesWeakAll(encloseBasis2(B[i], p), B)) { + return [B[i], p]; + } + } + + // If we get here then B must have at least two elements. + for (i = 0; i < B.length - 1; ++i) { + for (j = i + 1; j < B.length; ++j) { + if (enclosesNot(encloseBasis2(B[i], B[j]), p) + && enclosesNot(encloseBasis2(B[i], p), B[j]) + && enclosesNot(encloseBasis2(B[j], p), B[i]) + && enclosesWeakAll(encloseBasis3(B[i], B[j], p), B)) { + return [B[i], B[j], p]; + } + } + } + + // If we get here then something is very wrong. + throw new Error; +} + +function enclosesNot(a, b) { + var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y; + return dr < 0 || dr * dr < dx * dx + dy * dy; +} + +function enclosesWeak(a, b) { + var dr = a.r - b.r + 1e-6, dx = b.x - a.x, dy = b.y - a.y; + return dr > 0 && dr * dr > dx * dx + dy * dy; +} + +function enclosesWeakAll(a, B) { + for (var i = 0; i < B.length; ++i) { + if (!enclosesWeak(a, B[i])) { + return false; + } + } + return true; +} + +function encloseBasis(B) { + switch (B.length) { + case 1: return encloseBasis1(B[0]); + case 2: return encloseBasis2(B[0], B[1]); + case 3: return encloseBasis3(B[0], B[1], B[2]); + } +} + +function encloseBasis1(a) { + return { + x: a.x, + y: a.y, + r: a.r + }; +} + +function encloseBasis2(a, b) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1, + l = Math.sqrt(x21 * x21 + y21 * y21); + return { + x: (x1 + x2 + x21 / l * r21) / 2, + y: (y1 + y2 + y21 / l * r21) / 2, + r: (l + r1 + r2) / 2 + }; +} + +function encloseBasis3(a, b, c) { + var x1 = a.x, y1 = a.y, r1 = a.r, + x2 = b.x, y2 = b.y, r2 = b.r, + x3 = c.x, y3 = c.y, r3 = c.r, + a2 = x1 - x2, + a3 = x1 - x3, + b2 = y1 - y2, + b3 = y1 - y3, + c2 = r2 - r1, + c3 = r3 - r1, + d1 = x1 * x1 + y1 * y1 - r1 * r1, + d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2, + d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3, + ab = a3 * b2 - a2 * b3, + xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1, + xb = (b3 * c2 - b2 * c3) / ab, + ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1, + yb = (a2 * c3 - a3 * c2) / ab, + A = xb * xb + yb * yb - 1, + B = 2 * (r1 + xa * xb + ya * yb), + C = xa * xa + ya * ya - r1 * r1, + r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B); + return { + x: x1 + xa + xb * r, + y: y1 + ya + yb * r, + r: r + }; +} + +function place(a, b, c) { + var ax = a.x, + ay = a.y, + da = b.r + c.r, + db = a.r + c.r, + dx = b.x - ax, + dy = b.y - ay, + dc = dx * dx + dy * dy; + if (dc) { + var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc), + y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc); + c.x = ax + x * dx + y * dy; + c.y = ay + x * dy - y * dx; + } else { + c.x = ax + db; + c.y = ay; + } +} + +function intersects(a, b) { + var dx = b.x - a.x, + dy = b.y - a.y, + dr = a.r + b.r; + return dr * dr - 1e-6 > dx * dx + dy * dy; +} + +function score(node) { + var a = node._, + b = node.next._, + ab = a.r + b.r, + dx = (a.x * b.r + b.x * a.r) / ab, + dy = (a.y * b.r + b.y * a.r) / ab; + return dx * dx + dy * dy; +} + +function Node$1(circle) { + this._ = circle; + this.next = null; + this.previous = null; +} + +function packEnclose(circles) { + if (!(n = circles.length)) return 0; + + var a, b, c, n, aa, ca, i, j, k, sj, sk; + + // Place the first circle. + a = circles[0], a.x = 0, a.y = 0; + if (!(n > 1)) return a.r; + + // Place the second circle. + b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0; + if (!(n > 2)) return a.r + b.r; + + // Place the third circle. + place(b, a, c = circles[2]); + + // Initialize the front-chain using the first three circles a, b and c. + a = new Node$1(a), b = new Node$1(b), c = new Node$1(c); + a.next = c.previous = b; + b.next = a.previous = c; + c.next = b.previous = a; + + // Attempt to place each remaining circle… + pack: for (i = 3; i < n; ++i) { + place(a._, b._, c = circles[i]), c = new Node$1(c); + + // Find the closest intersecting circle on the front-chain, if any. + // “Closeness” is determined by linear distance along the front-chain. + // “Ahead” or “behind” is likewise determined by linear distance. + j = b.next, k = a.previous, sj = b._.r, sk = a._.r; + do { + if (sj <= sk) { + if (intersects(j._, c._)) { + b = j, a.next = b, b.previous = a, --i; + continue pack; + } + sj += j._.r, j = j.next; + } else { + if (intersects(k._, c._)) { + a = k, a.next = b, b.previous = a, --i; + continue pack; + } + sk += k._.r, k = k.previous; + } + } while (j !== k.next); + + // Success! Insert the new circle c between a and b. + c.previous = a, c.next = b, a.next = b.previous = b = c; + + // Compute the new closest circle pair to the centroid. + aa = score(a); + while ((c = c.next) !== b) { + if ((ca = score(c)) < aa) { + a = c, aa = ca; + } + } + b = a.next; + } + + // Compute the enclosing circle of the front chain. + a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a); + + // Translate the circles to put the enclosing circle around the origin. + for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y; + + return c.r; +} + +var siblings = function(circles) { + packEnclose(circles); + return circles; +}; + +function optional(f) { + return f == null ? null : required(f); +} + +function required(f) { + if (typeof f !== "function") throw new Error; + return f; +} + +function constantZero() { + return 0; +} + +var constant = function(x) { + return function() { + return x; + }; +}; + +function defaultRadius(d) { + return Math.sqrt(d.value); +} + +var index = function() { + var radius = null, + dx = 1, + dy = 1, + padding = constantZero; + + function pack(root) { + root.x = dx / 2, root.y = dy / 2; + if (radius) { + root.eachBefore(radiusLeaf(radius)) + .eachAfter(packChildren(padding, 0.5)) + .eachBefore(translateChild(1)); + } else { + root.eachBefore(radiusLeaf(defaultRadius)) + .eachAfter(packChildren(constantZero, 1)) + .eachAfter(packChildren(padding, root.r / Math.min(dx, dy))) + .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r))); + } + return root; + } + + pack.radius = function(x) { + return arguments.length ? (radius = optional(x), pack) : radius; + }; + + pack.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy]; + }; + + pack.padding = function(x) { + return arguments.length ? (padding = typeof x === "function" ? x : constant(+x), pack) : padding; + }; + + return pack; +}; + +function radiusLeaf(radius) { + return function(node) { + if (!node.children) { + node.r = Math.max(0, +radius(node) || 0); + } + }; +} + +function packChildren(padding, k) { + return function(node) { + if (children = node.children) { + var children, + i, + n = children.length, + r = padding(node) * k || 0, + e; + + if (r) for (i = 0; i < n; ++i) children[i].r += r; + e = packEnclose(children); + if (r) for (i = 0; i < n; ++i) children[i].r -= r; + node.r = e + r; + } + }; +} + +function translateChild(k) { + return function(node) { + var parent = node.parent; + node.r *= k; + if (parent) { + node.x = parent.x + k * node.x; + node.y = parent.y + k * node.y; + } + }; +} + +var roundNode = function(node) { + node.x0 = Math.round(node.x0); + node.y0 = Math.round(node.y0); + node.x1 = Math.round(node.x1); + node.y1 = Math.round(node.y1); +}; + +var treemapDice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (x1 - x0) / parent.value; + + while (++i < n) { + node = nodes[i], node.y0 = y0, node.y1 = y1; + node.x0 = x0, node.x1 = x0 += node.value * k; + } +}; + +var partition = function() { + var dx = 1, + dy = 1, + padding = 0, + round = false; + + function partition(root) { + var n = root.height + 1; + root.x0 = + root.y0 = padding; + root.x1 = dx; + root.y1 = dy / n; + root.eachBefore(positionNode(dy, n)); + if (round) root.eachBefore(roundNode); + return root; + } + + function positionNode(dy, n) { + return function(node) { + if (node.children) { + treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n); + } + var x0 = node.x0, + y0 = node.y0, + x1 = node.x1 - padding, + y1 = node.y1 - padding; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + }; + } + + partition.round = function(x) { + return arguments.length ? (round = !!x, partition) : round; + }; + + partition.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy]; + }; + + partition.padding = function(x) { + return arguments.length ? (padding = +x, partition) : padding; + }; + + return partition; +}; + +var keyPrefix = "$"; +var preroot = {depth: -1}; +var ambiguous = {}; + +function defaultId(d) { + return d.id; +} + +function defaultParentId(d) { + return d.parentId; +} + +var stratify = function() { + var id = defaultId, + parentId = defaultParentId; + + function stratify(data) { + var d, + i, + n = data.length, + root, + parent, + node, + nodes = new Array(n), + nodeId, + nodeKey, + nodeByKey = {}; + + for (i = 0; i < n; ++i) { + d = data[i], node = nodes[i] = new Node(d); + if ((nodeId = id(d, i, data)) != null && (nodeId += "")) { + nodeKey = keyPrefix + (node.id = nodeId); + nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node; + } + } + + for (i = 0; i < n; ++i) { + node = nodes[i], nodeId = parentId(data[i], i, data); + if (nodeId == null || !(nodeId += "")) { + if (root) throw new Error("multiple roots"); + root = node; + } else { + parent = nodeByKey[keyPrefix + nodeId]; + if (!parent) throw new Error("missing: " + nodeId); + if (parent === ambiguous) throw new Error("ambiguous: " + nodeId); + if (parent.children) parent.children.push(node); + else parent.children = [node]; + node.parent = parent; + } + } + + if (!root) throw new Error("no root"); + root.parent = preroot; + root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight); + root.parent = null; + if (n > 0) throw new Error("cycle"); + + return root; + } + + stratify.id = function(x) { + return arguments.length ? (id = required(x), stratify) : id; + }; + + stratify.parentId = function(x) { + return arguments.length ? (parentId = required(x), stratify) : parentId; + }; + + return stratify; +}; + +function defaultSeparation$1(a, b) { + return a.parent === b.parent ? 1 : 2; +} + +// function radialSeparation(a, b) { +// return (a.parent === b.parent ? 1 : 2) / a.depth; +// } + +// This function is used to traverse the left contour of a subtree (or +// subforest). It returns the successor of v on this contour. This successor is +// either given by the leftmost child of v or by the thread of v. The function +// returns null if and only if v is on the highest level of its subtree. +function nextLeft(v) { + var children = v.children; + return children ? children[0] : v.t; +} + +// This function works analogously to nextLeft. +function nextRight(v) { + var children = v.children; + return children ? children[children.length - 1] : v.t; +} + +// Shifts the current subtree rooted at w+. This is done by increasing +// prelim(w+) and mod(w+) by shift. +function moveSubtree(wm, wp, shift) { + var change = shift / (wp.i - wm.i); + wp.c -= change; + wp.s += shift; + wm.c += change; + wp.z += shift; + wp.m += shift; +} + +// All other shifts, applied to the smaller subtrees between w- and w+, are +// performed by this function. To prepare the shifts, we have to adjust +// change(w+), shift(w+), and change(w-). +function executeShifts(v) { + var shift = 0, + change = 0, + children = v.children, + i = children.length, + w; + while (--i >= 0) { + w = children[i]; + w.z += shift; + w.m += shift; + shift += w.s + (change += w.c); + } +} + +// If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise, +// returns the specified (default) ancestor. +function nextAncestor(vim, v, ancestor) { + return vim.a.parent === v.parent ? vim.a : ancestor; +} + +function TreeNode(node, i) { + this._ = node; + this.parent = null; + this.children = null; + this.A = null; // default ancestor + this.a = this; // ancestor + this.z = 0; // prelim + this.m = 0; // mod + this.c = 0; // change + this.s = 0; // shift + this.t = null; // thread + this.i = i; // number +} + +TreeNode.prototype = Object.create(Node.prototype); + +function treeRoot(root) { + var tree = new TreeNode(root, 0), + node, + nodes = [tree], + child, + children, + i, + n; + + while (node = nodes.pop()) { + if (children = node._.children) { + node.children = new Array(n = children.length); + for (i = n - 1; i >= 0; --i) { + nodes.push(child = node.children[i] = new TreeNode(children[i], i)); + child.parent = node; + } + } + } + + (tree.parent = new TreeNode(null, 0)).children = [tree]; + return tree; +} + +// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm +var tree = function() { + var separation = defaultSeparation$1, + dx = 1, + dy = 1, + nodeSize = null; + + function tree(root) { + var t = treeRoot(root); + + // Compute the layout using Buchheim et al.’s algorithm. + t.eachAfter(firstWalk), t.parent.m = -t.z; + t.eachBefore(secondWalk); + + // If a fixed node size is specified, scale x and y. + if (nodeSize) root.eachBefore(sizeNode); + + // If a fixed tree size is specified, scale x and y based on the extent. + // Compute the left-most, right-most, and depth-most nodes for extents. + else { + var left = root, + right = root, + bottom = root; + root.eachBefore(function(node) { + if (node.x < left.x) left = node; + if (node.x > right.x) right = node; + if (node.depth > bottom.depth) bottom = node; + }); + var s = left === right ? 1 : separation(left, right) / 2, + tx = s - left.x, + kx = dx / (right.x + s + tx), + ky = dy / (bottom.depth || 1); + root.eachBefore(function(node) { + node.x = (node.x + tx) * kx; + node.y = node.depth * ky; + }); + } + + return root; + } + + // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is + // applied recursively to the children of v, as well as the function + // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the + // node v is placed to the midpoint of its outermost children. + function firstWalk(v) { + var children = v.children, + siblings = v.parent.children, + w = v.i ? siblings[v.i - 1] : null; + if (children) { + executeShifts(v); + var midpoint = (children[0].z + children[children.length - 1].z) / 2; + if (w) { + v.z = w.z + separation(v._, w._); + v.m = v.z - midpoint; + } else { + v.z = midpoint; + } + } else if (w) { + v.z = w.z + separation(v._, w._); + } + v.parent.A = apportion(v, w, v.parent.A || siblings[0]); + } + + // Computes all real x-coordinates by summing up the modifiers recursively. + function secondWalk(v) { + v._.x = v.z + v.parent.m; + v.m += v.parent.m; + } + + // The core of the algorithm. Here, a new subtree is combined with the + // previous subtrees. Threads are used to traverse the inside and outside + // contours of the left and right subtree up to the highest common level. The + // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the + // superscript o means outside and i means inside, the subscript - means left + // subtree and + means right subtree. For summing up the modifiers along the + // contour, we use respective variables si+, si-, so-, and so+. Whenever two + // nodes of the inside contours conflict, we compute the left one of the + // greatest uncommon ancestors using the function ANCESTOR and call MOVE + // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees. + // Finally, we add a new thread (if necessary). + function apportion(v, w, ancestor) { + if (w) { + var vip = v, + vop = v, + vim = w, + vom = vip.parent.children[0], + sip = vip.m, + sop = vop.m, + sim = vim.m, + som = vom.m, + shift; + while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) { + vom = nextLeft(vom); + vop = nextRight(vop); + vop.a = v; + shift = vim.z + sim - vip.z - sip + separation(vim._, vip._); + if (shift > 0) { + moveSubtree(nextAncestor(vim, v, ancestor), v, shift); + sip += shift; + sop += shift; + } + sim += vim.m; + sip += vip.m; + som += vom.m; + sop += vop.m; + } + if (vim && !nextRight(vop)) { + vop.t = vim; + vop.m += sim - sop; + } + if (vip && !nextLeft(vom)) { + vom.t = vip; + vom.m += sip - som; + ancestor = v; + } + } + return ancestor; + } + + function sizeNode(node) { + node.x *= dx; + node.y = node.depth * dy; + } + + tree.separation = function(x) { + return arguments.length ? (separation = x, tree) : separation; + }; + + tree.size = function(x) { + return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]); + }; + + tree.nodeSize = function(x) { + return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null); + }; + + return tree; +}; + +var treemapSlice = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + node, + i = -1, + n = nodes.length, + k = parent.value && (y1 - y0) / parent.value; + + while (++i < n) { + node = nodes[i], node.x0 = x0, node.x1 = x1; + node.y0 = y0, node.y1 = y0 += node.value * k; + } +}; + +var phi = (1 + Math.sqrt(5)) / 2; + +function squarifyRatio(ratio, parent, x0, y0, x1, y1) { + var rows = [], + nodes = parent.children, + row, + nodeValue, + i0 = 0, + i1 = 0, + n = nodes.length, + dx, dy, + value = parent.value, + sumValue, + minValue, + maxValue, + newRatio, + minRatio, + alpha, + beta; + + while (i0 < n) { + dx = x1 - x0, dy = y1 - y0; + + // Find the next non-empty node. + do sumValue = nodes[i1++].value; while (!sumValue && i1 < n); + minValue = maxValue = sumValue; + alpha = Math.max(dy / dx, dx / dy) / (value * ratio); + beta = sumValue * sumValue * alpha; + minRatio = Math.max(maxValue / beta, beta / minValue); + + // Keep adding nodes while the aspect ratio maintains or improves. + for (; i1 < n; ++i1) { + sumValue += nodeValue = nodes[i1].value; + if (nodeValue < minValue) minValue = nodeValue; + if (nodeValue > maxValue) maxValue = nodeValue; + beta = sumValue * sumValue * alpha; + newRatio = Math.max(maxValue / beta, beta / minValue); + if (newRatio > minRatio) { sumValue -= nodeValue; break; } + minRatio = newRatio; + } + + // Position and record the row orientation. + rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)}); + if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1); + else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1); + value -= sumValue, i0 = i1; + } + + return rows; +} + +var squarify = ((function custom(ratio) { + + function squarify(parent, x0, y0, x1, y1) { + squarifyRatio(ratio, parent, x0, y0, x1, y1); + } + + squarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return squarify; +}))(phi); + +var index$1 = function() { + var tile = squarify, + round = false, + dx = 1, + dy = 1, + paddingStack = [0], + paddingInner = constantZero, + paddingTop = constantZero, + paddingRight = constantZero, + paddingBottom = constantZero, + paddingLeft = constantZero; + + function treemap(root) { + root.x0 = + root.y0 = 0; + root.x1 = dx; + root.y1 = dy; + root.eachBefore(positionNode); + paddingStack = [0]; + if (round) root.eachBefore(roundNode); + return root; + } + + function positionNode(node) { + var p = paddingStack[node.depth], + x0 = node.x0 + p, + y0 = node.y0 + p, + x1 = node.x1 - p, + y1 = node.y1 - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + node.x0 = x0; + node.y0 = y0; + node.x1 = x1; + node.y1 = y1; + if (node.children) { + p = paddingStack[node.depth + 1] = paddingInner(node) / 2; + x0 += paddingLeft(node) - p; + y0 += paddingTop(node) - p; + x1 -= paddingRight(node) - p; + y1 -= paddingBottom(node) - p; + if (x1 < x0) x0 = x1 = (x0 + x1) / 2; + if (y1 < y0) y0 = y1 = (y0 + y1) / 2; + tile(node, x0, y0, x1, y1); + } + } + + treemap.round = function(x) { + return arguments.length ? (round = !!x, treemap) : round; + }; + + treemap.size = function(x) { + return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy]; + }; + + treemap.tile = function(x) { + return arguments.length ? (tile = required(x), treemap) : tile; + }; + + treemap.padding = function(x) { + return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner(); + }; + + treemap.paddingInner = function(x) { + return arguments.length ? (paddingInner = typeof x === "function" ? x : constant(+x), treemap) : paddingInner; + }; + + treemap.paddingOuter = function(x) { + return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop(); + }; + + treemap.paddingTop = function(x) { + return arguments.length ? (paddingTop = typeof x === "function" ? x : constant(+x), treemap) : paddingTop; + }; + + treemap.paddingRight = function(x) { + return arguments.length ? (paddingRight = typeof x === "function" ? x : constant(+x), treemap) : paddingRight; + }; + + treemap.paddingBottom = function(x) { + return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant(+x), treemap) : paddingBottom; + }; + + treemap.paddingLeft = function(x) { + return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant(+x), treemap) : paddingLeft; + }; + + return treemap; +}; + +var binary = function(parent, x0, y0, x1, y1) { + var nodes = parent.children, + i, n = nodes.length, + sum, sums = new Array(n + 1); + + for (sums[0] = sum = i = 0; i < n; ++i) { + sums[i + 1] = sum += nodes[i].value; + } + + partition(0, n, parent.value, x0, y0, x1, y1); + + function partition(i, j, value, x0, y0, x1, y1) { + if (i >= j - 1) { + var node = nodes[i]; + node.x0 = x0, node.y0 = y0; + node.x1 = x1, node.y1 = y1; + return; + } + + var valueOffset = sums[i], + valueTarget = (value / 2) + valueOffset, + k = i + 1, + hi = j - 1; + + while (k < hi) { + var mid = k + hi >>> 1; + if (sums[mid] < valueTarget) k = mid + 1; + else hi = mid; + } + + if ((valueTarget - sums[k - 1]) < (sums[k] - valueTarget) && i + 1 < k) --k; + + var valueLeft = sums[k] - valueOffset, + valueRight = value - valueLeft; + + if ((x1 - x0) > (y1 - y0)) { + var xk = (x0 * valueRight + x1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, xk, y1); + partition(k, j, valueRight, xk, y0, x1, y1); + } else { + var yk = (y0 * valueRight + y1 * valueLeft) / value; + partition(i, k, valueLeft, x0, y0, x1, yk); + partition(k, j, valueRight, x0, yk, x1, y1); + } + } +}; + +var sliceDice = function(parent, x0, y0, x1, y1) { + (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1); +}; + +var resquarify = ((function custom(ratio) { + + function resquarify(parent, x0, y0, x1, y1) { + if ((rows = parent._squarify) && (rows.ratio === ratio)) { + var rows, + row, + nodes, + i, + j = -1, + n, + m = rows.length, + value = parent.value; + + while (++j < m) { + row = rows[j], nodes = row.children; + for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value; + if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value); + else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1); + value -= row.value; + } + } else { + parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1); + rows.ratio = ratio; + } + } + + resquarify.ratio = function(x) { + return custom((x = +x) > 1 ? x : 1); + }; + + return resquarify; +}))(phi); + +exports.cluster = cluster; +exports.hierarchy = hierarchy; +exports.pack = index; +exports.packSiblings = siblings; +exports.packEnclose = enclose; +exports.partition = partition; +exports.stratify = stratify; +exports.tree = tree; +exports.treemap = index$1; +exports.treemapBinary = binary; +exports.treemapDice = treemapDice; +exports.treemapSlice = treemapSlice; +exports.treemapSliceDice = sliceDice; +exports.treemapSquarify = squarify; +exports.treemapResquarify = resquarify; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],37:[function(require,module,exports){ +// https://d3js.org/d3-interpolate/ Version 1.1.6. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-color')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-color'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3)); +}(this, (function (exports,d3Color) { 'use strict'; + +function basis(t1, v0, v1, v2, v3) { + var t2 = t1 * t1, t3 = t2 * t1; + return ((1 - 3 * t1 + 3 * t2 - t3) * v0 + + (4 - 6 * t2 + 3 * t3) * v1 + + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2 + + t3 * v3) / 6; +} + +var basis$1 = function(values) { + var n = values.length - 1; + return function(t) { + var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), + v1 = values[i], + v2 = values[i + 1], + v0 = i > 0 ? values[i - 1] : 2 * v1 - v2, + v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +}; + +var basisClosed = function(values) { + var n = values.length; + return function(t) { + var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), + v0 = values[(i + n - 1) % n], + v1 = values[i % n], + v2 = values[(i + 1) % n], + v3 = values[(i + 2) % n]; + return basis((t - i / n) * n, v0, v1, v2, v3); + }; +}; + +var constant = function(x) { + return function() { + return x; + }; +}; + +function linear(a, d) { + return function(t) { + return a + t * d; + }; +} + +function exponential(a, b, y) { + return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) { + return Math.pow(a + t * b, y); + }; +} + +function hue(a, b) { + var d = b - a; + return d ? linear(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant(isNaN(a) ? b : a); +} + +function gamma(y) { + return (y = +y) === 1 ? nogamma : function(a, b) { + return b - a ? exponential(a, b, y) : constant(isNaN(a) ? b : a); + }; +} + +function nogamma(a, b) { + var d = b - a; + return d ? linear(a, d) : constant(isNaN(a) ? b : a); +} + +var rgb$1 = ((function rgbGamma(y) { + var color$$1 = gamma(y); + + function rgb$$1(start, end) { + var r = color$$1((start = d3Color.rgb(start)).r, (end = d3Color.rgb(end)).r), + g = color$$1(start.g, end.g), + b = color$$1(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.r = r(t); + start.g = g(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; + } + + rgb$$1.gamma = rgbGamma; + + return rgb$$1; +}))(1); + +function rgbSpline(spline) { + return function(colors) { + var n = colors.length, + r = new Array(n), + g = new Array(n), + b = new Array(n), + i, color$$1; + for (i = 0; i < n; ++i) { + color$$1 = d3Color.rgb(colors[i]); + r[i] = color$$1.r || 0; + g[i] = color$$1.g || 0; + b[i] = color$$1.b || 0; + } + r = spline(r); + g = spline(g); + b = spline(b); + color$$1.opacity = 1; + return function(t) { + color$$1.r = r(t); + color$$1.g = g(t); + color$$1.b = b(t); + return color$$1 + ""; + }; + }; +} + +var rgbBasis = rgbSpline(basis$1); +var rgbBasisClosed = rgbSpline(basisClosed); + +var array = function(a, b) { + var nb = b ? b.length : 0, + na = a ? Math.min(nb, a.length) : 0, + x = new Array(na), + c = new Array(nb), + i; + + for (i = 0; i < na; ++i) x[i] = value(a[i], b[i]); + for (; i < nb; ++i) c[i] = b[i]; + + return function(t) { + for (i = 0; i < na; ++i) c[i] = x[i](t); + return c; + }; +}; + +var date = function(a, b) { + var d = new Date; + return a = +a, b -= a, function(t) { + return d.setTime(a + b * t), d; + }; +}; + +var number = function(a, b) { + return a = +a, b -= a, function(t) { + return a + b * t; + }; +}; + +var object = function(a, b) { + var i = {}, + c = {}, + k; + + if (a === null || typeof a !== "object") a = {}; + if (b === null || typeof b !== "object") b = {}; + + for (k in b) { + if (k in a) { + i[k] = value(a[k], b[k]); + } else { + c[k] = b[k]; + } + } + + return function(t) { + for (k in i) c[k] = i[k](t); + return c; + }; +}; + +var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g; +var reB = new RegExp(reA.source, "g"); + +function zero(b) { + return function() { + return b; + }; +} + +function one(b) { + return function(t) { + return b(t) + ""; + }; +} + +var string = function(a, b) { + var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b + am, // current match in a + bm, // current match in b + bs, // string preceding current number in b, if any + i = -1, // index in s + s = [], // string constants and placeholders + q = []; // number interpolators + + // Coerce inputs to strings. + a = a + "", b = b + ""; + + // Interpolate pairs of numbers in a & b. + while ((am = reA.exec(a)) + && (bm = reB.exec(b))) { + if ((bs = bm.index) > bi) { // a string precedes the next number in b + bs = b.slice(bi, bs); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match + if (s[i]) s[i] += bm; // coalesce with previous string + else s[++i] = bm; + } else { // interpolate non-matching numbers + s[++i] = null; + q.push({i: i, x: number(am, bm)}); + } + bi = reB.lastIndex; + } + + // Add remains of b. + if (bi < b.length) { + bs = b.slice(bi); + if (s[i]) s[i] += bs; // coalesce with previous string + else s[++i] = bs; + } + + // Special optimization for only a single match. + // Otherwise, interpolate each of the numbers and rejoin the string. + return s.length < 2 ? (q[0] + ? one(q[0].x) + : zero(b)) + : (b = q.length, function(t) { + for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }); +}; + +var value = function(a, b) { + var t = typeof b, c; + return b == null || t === "boolean" ? constant(b) + : (t === "number" ? number + : t === "string" ? ((c = d3Color.color(b)) ? (b = c, rgb$1) : string) + : b instanceof d3Color.color ? rgb$1 + : b instanceof Date ? date + : Array.isArray(b) ? array + : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object + : number)(a, b); +}; + +var round = function(a, b) { + return a = +a, b -= a, function(t) { + return Math.round(a + b * t); + }; +}; + +var degrees = 180 / Math.PI; + +var identity = { + translateX: 0, + translateY: 0, + rotate: 0, + skewX: 0, + scaleX: 1, + scaleY: 1 +}; + +var decompose = function(a, b, c, d, e, f) { + var scaleX, scaleY, skewX; + if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX; + if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX; + if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY; + if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX; + return { + translateX: e, + translateY: f, + rotate: Math.atan2(b, a) * degrees, + skewX: Math.atan(skewX) * degrees, + scaleX: scaleX, + scaleY: scaleY + }; +}; + +var cssNode; +var cssRoot; +var cssView; +var svgNode; + +function parseCss(value) { + if (value === "none") return identity; + if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView; + cssNode.style.transform = value; + value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform"); + cssRoot.removeChild(cssNode); + value = value.slice(7, -1).split(","); + return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]); +} + +function parseSvg(value) { + if (value == null) return identity; + if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g"); + svgNode.setAttribute("transform", value); + if (!(value = svgNode.transform.baseVal.consolidate())) return identity; + value = value.matrix; + return decompose(value.a, value.b, value.c, value.d, value.e, value.f); +} + +function interpolateTransform(parse, pxComma, pxParen, degParen) { + + function pop(s) { + return s.length ? s.pop() + " " : ""; + } + + function translate(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push("translate(", null, pxComma, null, pxParen); + q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); + } else if (xb || yb) { + s.push("translate(" + xb + pxComma + yb + pxParen); + } + } + + function rotate(a, b, s, q) { + if (a !== b) { + if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path + q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: number(a, b)}); + } else if (b) { + s.push(pop(s) + "rotate(" + b + degParen); + } + } + + function skewX(a, b, s, q) { + if (a !== b) { + q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: number(a, b)}); + } else if (b) { + s.push(pop(s) + "skewX(" + b + degParen); + } + } + + function scale(xa, ya, xb, yb, s, q) { + if (xa !== xb || ya !== yb) { + var i = s.push(pop(s) + "scale(", null, ",", null, ")"); + q.push({i: i - 4, x: number(xa, xb)}, {i: i - 2, x: number(ya, yb)}); + } else if (xb !== 1 || yb !== 1) { + s.push(pop(s) + "scale(" + xb + "," + yb + ")"); + } + } + + return function(a, b) { + var s = [], // string constants and placeholders + q = []; // number interpolators + a = parse(a), b = parse(b); + translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q); + rotate(a.rotate, b.rotate, s, q); + skewX(a.skewX, b.skewX, s, q); + scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q); + a = b = null; // gc + return function(t) { + var i = -1, n = q.length, o; + while (++i < n) s[(o = q[i]).i] = o.x(t); + return s.join(""); + }; + }; +} + +var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)"); +var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")"); + +var rho = Math.SQRT2; +var rho2 = 2; +var rho4 = 4; +var epsilon2 = 1e-12; + +function cosh(x) { + return ((x = Math.exp(x)) + 1 / x) / 2; +} + +function sinh(x) { + return ((x = Math.exp(x)) - 1 / x) / 2; +} + +function tanh(x) { + return ((x = Math.exp(2 * x)) - 1) / (x + 1); +} + +// p0 = [ux0, uy0, w0] +// p1 = [ux1, uy1, w1] +var zoom = function(p0, p1) { + var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], + ux1 = p1[0], uy1 = p1[1], w1 = p1[2], + dx = ux1 - ux0, + dy = uy1 - uy0, + d2 = dx * dx + dy * dy, + i, + S; + + // Special case for u0 ≅ u1. + if (d2 < epsilon2) { + S = Math.log(w1 / w0) / rho; + i = function(t) { + return [ + ux0 + t * dx, + uy0 + t * dy, + w0 * Math.exp(rho * t * S) + ]; + }; + } + + // General case. + else { + var d1 = Math.sqrt(d2), + b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), + b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), + r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), + r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1); + S = (r1 - r0) / rho; + i = function(t) { + var s = t * S, + coshr0 = cosh(r0), + u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0)); + return [ + ux0 + u * dx, + uy0 + u * dy, + w0 * coshr0 / cosh(rho * s + r0) + ]; + }; + } + + i.duration = S * 1000; + + return i; +}; + +function hsl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = d3Color.hsl(start)).h, (end = d3Color.hsl(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hsl$2 = hsl$1(hue); +var hslLong = hsl$1(nogamma); + +function lab$1(start, end) { + var l = nogamma((start = d3Color.lab(start)).l, (end = d3Color.lab(end)).l), + a = nogamma(start.a, end.a), + b = nogamma(start.b, end.b), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.l = l(t); + start.a = a(t); + start.b = b(t); + start.opacity = opacity(t); + return start + ""; + }; +} + +function hcl$1(hue$$1) { + return function(start, end) { + var h = hue$$1((start = d3Color.hcl(start)).h, (end = d3Color.hcl(end)).h), + c = nogamma(start.c, end.c), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.c = c(t); + start.l = l(t); + start.opacity = opacity(t); + return start + ""; + }; + } +} + +var hcl$2 = hcl$1(hue); +var hclLong = hcl$1(nogamma); + +function cubehelix$1(hue$$1) { + return (function cubehelixGamma(y) { + y = +y; + + function cubehelix$$1(start, end) { + var h = hue$$1((start = d3Color.cubehelix(start)).h, (end = d3Color.cubehelix(end)).h), + s = nogamma(start.s, end.s), + l = nogamma(start.l, end.l), + opacity = nogamma(start.opacity, end.opacity); + return function(t) { + start.h = h(t); + start.s = s(t); + start.l = l(Math.pow(t, y)); + start.opacity = opacity(t); + return start + ""; + }; + } + + cubehelix$$1.gamma = cubehelixGamma; + + return cubehelix$$1; + })(1); +} + +var cubehelix$2 = cubehelix$1(hue); +var cubehelixLong = cubehelix$1(nogamma); + +var quantize = function(interpolator, n) { + var samples = new Array(n); + for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1)); + return samples; +}; + +exports.interpolate = value; +exports.interpolateArray = array; +exports.interpolateBasis = basis$1; +exports.interpolateBasisClosed = basisClosed; +exports.interpolateDate = date; +exports.interpolateNumber = number; +exports.interpolateObject = object; +exports.interpolateRound = round; +exports.interpolateString = string; +exports.interpolateTransformCss = interpolateTransformCss; +exports.interpolateTransformSvg = interpolateTransformSvg; +exports.interpolateZoom = zoom; +exports.interpolateRgb = rgb$1; +exports.interpolateRgbBasis = rgbBasis; +exports.interpolateRgbBasisClosed = rgbBasisClosed; +exports.interpolateHsl = hsl$2; +exports.interpolateHslLong = hslLong; +exports.interpolateLab = lab$1; +exports.interpolateHcl = hcl$2; +exports.interpolateHclLong = hclLong; +exports.interpolateCubehelix = cubehelix$2; +exports.interpolateCubehelixLong = cubehelixLong; +exports.quantize = quantize; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-color":28}],38:[function(require,module,exports){ +// https://d3js.org/d3-path/ Version 1.0.5. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var pi = Math.PI; +var tau = 2 * pi; +var epsilon = 1e-6; +var tauEpsilon = tau - epsilon; + +function Path() { + this._x0 = this._y0 = // start of current subpath + this._x1 = this._y1 = null; // end of current subpath + this._ = ""; +} + +function path() { + return new Path; +} + +Path.prototype = path.prototype = { + constructor: Path, + moveTo: function(x, y) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y); + }, + closePath: function() { + if (this._x1 !== null) { + this._x1 = this._x0, this._y1 = this._y0; + this._ += "Z"; + } + }, + lineTo: function(x, y) { + this._ += "L" + (this._x1 = +x) + "," + (this._y1 = +y); + }, + quadraticCurveTo: function(x1, y1, x, y) { + this._ += "Q" + (+x1) + "," + (+y1) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { + this._ += "C" + (+x1) + "," + (+y1) + "," + (+x2) + "," + (+y2) + "," + (this._x1 = +x) + "," + (this._y1 = +y); + }, + arcTo: function(x1, y1, x2, y2, r) { + x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r; + var x0 = this._x1, + y0 = this._y1, + x21 = x2 - x1, + y21 = y2 - y1, + x01 = x0 - x1, + y01 = y0 - y1, + l01_2 = x01 * x01 + y01 * y01; + + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x1,y1). + if (this._x1 === null) { + this._ += "M" + (this._x1 = x1) + "," + (this._y1 = y1); + } + + // Or, is (x1,y1) coincident with (x0,y0)? Do nothing. + else if (!(l01_2 > epsilon)) {} + + // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear? + // Equivalently, is (x1,y1) coincident with (x2,y2)? + // Or, is the radius zero? Line to (x1,y1). + else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) { + this._ += "L" + (this._x1 = x1) + "," + (this._y1 = y1); + } + + // Otherwise, draw an arc! + else { + var x20 = x2 - x0, + y20 = y2 - y0, + l21_2 = x21 * x21 + y21 * y21, + l20_2 = x20 * x20 + y20 * y20, + l21 = Math.sqrt(l21_2), + l01 = Math.sqrt(l01_2), + l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), + t01 = l / l01, + t21 = l / l21; + + // If the start tangent is not coincident with (x0,y0), line to. + if (Math.abs(t01 - 1) > epsilon) { + this._ += "L" + (x1 + t01 * x01) + "," + (y1 + t01 * y01); + } + + this._ += "A" + r + "," + r + ",0,0," + (+(y01 * x20 > x01 * y20)) + "," + (this._x1 = x1 + t21 * x21) + "," + (this._y1 = y1 + t21 * y21); + } + }, + arc: function(x, y, r, a0, a1, ccw) { + x = +x, y = +y, r = +r; + var dx = r * Math.cos(a0), + dy = r * Math.sin(a0), + x0 = x + dx, + y0 = y + dy, + cw = 1 ^ ccw, + da = ccw ? a0 - a1 : a1 - a0; + + // Is the radius negative? Error. + if (r < 0) throw new Error("negative radius: " + r); + + // Is this path empty? Move to (x0,y0). + if (this._x1 === null) { + this._ += "M" + x0 + "," + y0; + } + + // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0). + else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) { + this._ += "L" + x0 + "," + y0; + } + + // Is this arc empty? We’re done. + if (!r) return; + + // Does the angle go the wrong way? Flip the direction. + if (da < 0) da = da % tau + tau; + + // Is this a complete circle? Draw two arcs to complete the circle. + if (da > tauEpsilon) { + this._ += "A" + r + "," + r + ",0,1," + cw + "," + (x - dx) + "," + (y - dy) + "A" + r + "," + r + ",0,1," + cw + "," + (this._x1 = x0) + "," + (this._y1 = y0); + } + + // Is this arc non-empty? Draw an arc! + else if (da > epsilon) { + this._ += "A" + r + "," + r + ",0," + (+(da >= pi)) + "," + cw + "," + (this._x1 = x + r * Math.cos(a1)) + "," + (this._y1 = y + r * Math.sin(a1)); + } + }, + rect: function(x, y, w, h) { + this._ += "M" + (this._x0 = this._x1 = +x) + "," + (this._y0 = this._y1 = +y) + "h" + (+w) + "v" + (+h) + "h" + (-w) + "Z"; + }, + toString: function() { + return this._; + } +}; + +exports.path = path; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],39:[function(require,module,exports){ +// https://d3js.org/d3-polygon/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var area = function(polygon) { + var i = -1, + n = polygon.length, + a, + b = polygon[n - 1], + area = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + area += a[1] * b[0] - a[0] * b[1]; + } + + return area / 2; +}; + +var centroid = function(polygon) { + var i = -1, + n = polygon.length, + x = 0, + y = 0, + a, + b = polygon[n - 1], + c, + k = 0; + + while (++i < n) { + a = b; + b = polygon[i]; + k += c = a[0] * b[1] - b[0] * a[1]; + x += (a[0] + b[0]) * c; + y += (a[1] + b[1]) * c; + } + + return k *= 3, [x / k, y / k]; +}; + +// Returns the 2D cross product of AB and AC vectors, i.e., the z-component of +// the 3D cross product in a quadrant I Cartesian coordinate system (+x is +// right, +y is up). Returns a positive value if ABC is counter-clockwise, +// negative if clockwise, and zero if the points are collinear. +var cross = function(a, b, c) { + return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]); +}; + +function lexicographicOrder(a, b) { + return a[0] - b[0] || a[1] - b[1]; +} + +// Computes the upper convex hull per the monotone chain algorithm. +// Assumes points.length >= 3, is sorted by x, unique in y. +// Returns an array of indices into points in left-to-right order. +function computeUpperHullIndexes(points) { + var n = points.length, + indexes = [0, 1], + size = 2; + + for (var i = 2; i < n; ++i) { + while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size; + indexes[size++] = i; + } + + return indexes.slice(0, size); // remove popped points +} + +var hull = function(points) { + if ((n = points.length) < 3) return null; + + var i, + n, + sortedPoints = new Array(n), + flippedPoints = new Array(n); + + for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i]; + sortedPoints.sort(lexicographicOrder); + for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]]; + + var upperIndexes = computeUpperHullIndexes(sortedPoints), + lowerIndexes = computeUpperHullIndexes(flippedPoints); + + // Construct the hull polygon, removing possible duplicate endpoints. + var skipLeft = lowerIndexes[0] === upperIndexes[0], + skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1], + hull = []; + + // Add upper hull in right-to-l order. + // Then add lower hull in left-to-right order. + for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]); + for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]); + + return hull; +}; + +var contains = function(polygon, point) { + var n = polygon.length, + p = polygon[n - 1], + x = point[0], y = point[1], + x0 = p[0], y0 = p[1], + x1, y1, + inside = false; + + for (var i = 0; i < n; ++i) { + p = polygon[i], x1 = p[0], y1 = p[1]; + if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside; + x0 = x1, y0 = y1; + } + + return inside; +}; + +var length = function(polygon) { + var i = -1, + n = polygon.length, + b = polygon[n - 1], + xa, + ya, + xb = b[0], + yb = b[1], + perimeter = 0; + + while (++i < n) { + xa = xb; + ya = yb; + b = polygon[i]; + xb = b[0]; + yb = b[1]; + xa -= xb; + ya -= yb; + perimeter += Math.sqrt(xa * xa + ya * ya); + } + + return perimeter; +}; + +exports.polygonArea = area; +exports.polygonCentroid = centroid; +exports.polygonHull = hull; +exports.polygonContains = contains; +exports.polygonLength = length; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],40:[function(require,module,exports){ +// https://d3js.org/d3-quadtree/ Version 1.0.3. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var tree_add = function(d) { + var x = +this._x.call(null, d), + y = +this._y.call(null, d); + return add(this.cover(x, y), x, y, d); +}; + +function add(tree, x, y, d) { + if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points + + var parent, + node = tree._root, + leaf = {data: d}, + x0 = tree._x0, + y0 = tree._y0, + x1 = tree._x1, + y1 = tree._y1, + xm, + ym, + xp, + yp, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return tree._root = leaf, tree; + + // Find the existing leaf for the new point, or add it. + while (node.length) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree; + } + + // Is the new point is exactly coincident with the existing point? + xp = +tree._x.call(null, node.data); + yp = +tree._y.call(null, node.data); + if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree; + + // Otherwise, split the leaf node until the old and new point are separated. + do { + parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4); + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm))); + return parent[j] = node, parent[i] = leaf, tree; +} + +function addAll(data) { + var d, i, n = data.length, + x, + y, + xz = new Array(n), + yz = new Array(n), + x0 = Infinity, + y0 = Infinity, + x1 = -Infinity, + y1 = -Infinity; + + // Compute the points and their extent. + for (i = 0; i < n; ++i) { + if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue; + xz[i] = x; + yz[i] = y; + if (x < x0) x0 = x; + if (x > x1) x1 = x; + if (y < y0) y0 = y; + if (y > y1) y1 = y; + } + + // If there were no (valid) points, inherit the existing extent. + if (x1 < x0) x0 = this._x0, x1 = this._x1; + if (y1 < y0) y0 = this._y0, y1 = this._y1; + + // Expand the tree to cover the new points. + this.cover(x0, y0).cover(x1, y1); + + // Add the new points. + for (i = 0; i < n; ++i) { + add(this, xz[i], yz[i], data[i]); + } + + return this; +} + +var tree_cover = function(x, y) { + if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points + + var x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1; + + // If the quadtree has no extent, initialize them. + // Integer extent are necessary so that if we later double the extent, + // the existing quadrant boundaries don’t change due to floating point error! + if (isNaN(x0)) { + x1 = (x0 = Math.floor(x)) + 1; + y1 = (y0 = Math.floor(y)) + 1; + } + + // Otherwise, double repeatedly to cover. + else if (x0 > x || x > x1 || y0 > y || y > y1) { + var z = x1 - x0, + node = this._root, + parent, + i; + + switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) { + case 0: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1); + break; + } + case 1: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1); + break; + } + case 2: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y); + break; + } + case 3: { + do parent = new Array(4), parent[i] = node, node = parent; + while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y); + break; + } + } + + if (this._root && this._root.length) this._root = node; + } + + // If the quadtree covers the point already, just return. + else return this; + + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + return this; +}; + +var tree_data = function() { + var data = []; + this.visit(function(node) { + if (!node.length) do data.push(node.data); while (node = node.next) + }); + return data; +}; + +var tree_extent = function(_) { + return arguments.length + ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1]) + : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]]; +}; + +var Quad = function(node, x0, y0, x1, y1) { + this.node = node; + this.x0 = x0; + this.y0 = y0; + this.x1 = x1; + this.y1 = y1; +}; + +var tree_find = function(x, y, radius) { + var data, + x0 = this._x0, + y0 = this._y0, + x1, + y1, + x2, + y2, + x3 = this._x1, + y3 = this._y1, + quads = [], + node = this._root, + q, + i; + + if (node) quads.push(new Quad(node, x0, y0, x3, y3)); + if (radius == null) radius = Infinity; + else { + x0 = x - radius, y0 = y - radius; + x3 = x + radius, y3 = y + radius; + radius *= radius; + } + + while (q = quads.pop()) { + + // Stop searching if this quadrant can’t contain a closer node. + if (!(node = q.node) + || (x1 = q.x0) > x3 + || (y1 = q.y0) > y3 + || (x2 = q.x1) < x0 + || (y2 = q.y1) < y0) continue; + + // Bisect the current quadrant. + if (node.length) { + var xm = (x1 + x2) / 2, + ym = (y1 + y2) / 2; + + quads.push( + new Quad(node[3], xm, ym, x2, y2), + new Quad(node[2], x1, ym, xm, y2), + new Quad(node[1], xm, y1, x2, ym), + new Quad(node[0], x1, y1, xm, ym) + ); + + // Visit the closest quadrant first. + if (i = (y >= ym) << 1 | (x >= xm)) { + q = quads[quads.length - 1]; + quads[quads.length - 1] = quads[quads.length - 1 - i]; + quads[quads.length - 1 - i] = q; + } + } + + // Visit this point. (Visiting coincident points isn’t necessary!) + else { + var dx = x - +this._x.call(null, node.data), + dy = y - +this._y.call(null, node.data), + d2 = dx * dx + dy * dy; + if (d2 < radius) { + var d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = node.data; + } + } + } + + return data; +}; + +var tree_remove = function(d) { + if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points + + var parent, + node = this._root, + retainer, + previous, + next, + x0 = this._x0, + y0 = this._y0, + x1 = this._x1, + y1 = this._y1, + x, + y, + xm, + ym, + right, + bottom, + i, + j; + + // If the tree is empty, initialize the root as a leaf. + if (!node) return this; + + // Find the leaf node for the point. + // While descending, also retain the deepest parent with a non-removed sibling. + if (node.length) while (true) { + if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm; + if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym; + if (!(parent = node, node = node[i = bottom << 1 | right])) return this; + if (!node.length) break; + if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i; + } + + // Find the point to remove. + while (node.data !== d) if (!(previous = node, node = node.next)) return this; + if (next = node.next) delete node.next; + + // If there are multiple coincident points, remove just the point. + if (previous) return (next ? previous.next = next : delete previous.next), this; + + // If this is the root point, remove it. + if (!parent) return this._root = next, this; + + // Remove this leaf. + next ? parent[i] = next : delete parent[i]; + + // If the parent now contains exactly one leaf, collapse superfluous parents. + if ((node = parent[0] || parent[1] || parent[2] || parent[3]) + && node === (parent[3] || parent[2] || parent[1] || parent[0]) + && !node.length) { + if (retainer) retainer[j] = node; + else this._root = node; + } + + return this; +}; + +function removeAll(data) { + for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]); + return this; +} + +var tree_root = function() { + return this._root; +}; + +var tree_size = function() { + var size = 0; + this.visit(function(node) { + if (!node.length) do ++size; while (node = node.next) + }); + return size; +}; + +var tree_visit = function(callback) { + var quads = [], q, node = this._root, child, x0, y0, x1, y1; + if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) { + var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + } + } + return this; +}; + +var tree_visitAfter = function(callback) { + var quads = [], next = [], q; + if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1)); + while (q = quads.pop()) { + var node = q.node; + if (node.length) { + var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2; + if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym)); + if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym)); + if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1)); + if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1)); + } + next.push(q); + } + while (q = next.pop()) { + callback(q.node, q.x0, q.y0, q.x1, q.y1); + } + return this; +}; + +function defaultX(d) { + return d[0]; +} + +var tree_x = function(_) { + return arguments.length ? (this._x = _, this) : this._x; +}; + +function defaultY(d) { + return d[1]; +} + +var tree_y = function(_) { + return arguments.length ? (this._y = _, this) : this._y; +}; + +function quadtree(nodes, x, y) { + var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN); + return nodes == null ? tree : tree.addAll(nodes); +} + +function Quadtree(x, y, x0, y0, x1, y1) { + this._x = x; + this._y = y; + this._x0 = x0; + this._y0 = y0; + this._x1 = x1; + this._y1 = y1; + this._root = undefined; +} + +function leaf_copy(leaf) { + var copy = {data: leaf.data}, next = copy; + while (leaf = leaf.next) next = next.next = {data: leaf.data}; + return copy; +} + +var treeProto = quadtree.prototype = Quadtree.prototype; + +treeProto.copy = function() { + var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1), + node = this._root, + nodes, + child; + + if (!node) return copy; + + if (!node.length) return copy._root = leaf_copy(node), copy; + + nodes = [{source: node, target: copy._root = new Array(4)}]; + while (node = nodes.pop()) { + for (var i = 0; i < 4; ++i) { + if (child = node.source[i]) { + if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)}); + else node.target[i] = leaf_copy(child); + } + } + } + + return copy; +}; + +treeProto.add = tree_add; +treeProto.addAll = addAll; +treeProto.cover = tree_cover; +treeProto.data = tree_data; +treeProto.extent = tree_extent; +treeProto.find = tree_find; +treeProto.remove = tree_remove; +treeProto.removeAll = removeAll; +treeProto.root = tree_root; +treeProto.size = tree_size; +treeProto.visit = tree_visit; +treeProto.visitAfter = tree_visitAfter; +treeProto.x = tree_x; +treeProto.y = tree_y; + +exports.quadtree = quadtree; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],41:[function(require,module,exports){ +// https://d3js.org/d3-queue/ Version 3.0.7. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var slice = [].slice; + +var noabort = {}; + +function Queue(size) { + this._size = size; + this._call = + this._error = null; + this._tasks = []; + this._data = []; + this._waiting = + this._active = + this._ended = + this._start = 0; // inside a synchronous task callback? +} + +Queue.prototype = queue.prototype = { + constructor: Queue, + defer: function(callback) { + if (typeof callback !== "function") throw new Error("invalid callback"); + if (this._call) throw new Error("defer after await"); + if (this._error != null) return this; + var t = slice.call(arguments, 1); + t.push(callback); + ++this._waiting, this._tasks.push(t); + poke(this); + return this; + }, + abort: function() { + if (this._error == null) abort(this, new Error("abort")); + return this; + }, + await: function(callback) { + if (typeof callback !== "function") throw new Error("invalid callback"); + if (this._call) throw new Error("multiple await"); + this._call = function(error, results) { callback.apply(null, [error].concat(results)); }; + maybeNotify(this); + return this; + }, + awaitAll: function(callback) { + if (typeof callback !== "function") throw new Error("invalid callback"); + if (this._call) throw new Error("multiple await"); + this._call = callback; + maybeNotify(this); + return this; + } +}; + +function poke(q) { + if (!q._start) { + try { start(q); } // let the current task complete + catch (e) { + if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously + else if (!q._data) throw e; // await callback errored synchronously + } + } +} + +function start(q) { + while (q._start = q._waiting && q._active < q._size) { + var i = q._ended + q._active, + t = q._tasks[i], + j = t.length - 1, + c = t[j]; + t[j] = end(q, i); + --q._waiting, ++q._active; + t = c.apply(null, t); + if (!q._tasks[i]) continue; // task finished synchronously + q._tasks[i] = t || noabort; + } +} + +function end(q, i) { + return function(e, r) { + if (!q._tasks[i]) return; // ignore multiple callbacks + --q._active, ++q._ended; + q._tasks[i] = null; + if (q._error != null) return; // ignore secondary errors + if (e != null) { + abort(q, e); + } else { + q._data[i] = r; + if (q._waiting) poke(q); + else maybeNotify(q); + } + }; +} + +function abort(q, e) { + var i = q._tasks.length, t; + q._error = e; // ignore active callbacks + q._data = undefined; // allow gc + q._waiting = NaN; // prevent starting + + while (--i >= 0) { + if (t = q._tasks[i]) { + q._tasks[i] = null; + if (t.abort) { + try { t.abort(); } + catch (e) { /* ignore */ } + } + } + } + + q._active = NaN; // allow notification + maybeNotify(q); +} + +function maybeNotify(q) { + if (!q._active && q._call) { + var d = q._data; + q._data = undefined; // allow gc + q._call(q._error, d); + } +} + +function queue(concurrency) { + if (concurrency == null) concurrency = Infinity; + else if (!((concurrency = +concurrency) >= 1)) throw new Error("invalid concurrency"); + return new Queue(concurrency); +} + +exports.queue = queue; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],42:[function(require,module,exports){ +// https://d3js.org/d3-random/ Version 1.1.0. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var defaultSource = function() { + return Math.random(); +}; + +var uniform = ((function sourceRandomUniform(source) { + function randomUniform(min, max) { + min = min == null ? 0 : +min; + max = max == null ? 1 : +max; + if (arguments.length === 1) max = min, min = 0; + else max -= min; + return function() { + return source() * max + min; + }; + } + + randomUniform.source = sourceRandomUniform; + + return randomUniform; +}))(defaultSource); + +var normal = ((function sourceRandomNormal(source) { + function randomNormal(mu, sigma) { + var x, r; + mu = mu == null ? 0 : +mu; + sigma = sigma == null ? 1 : +sigma; + return function() { + var y; + + // If available, use the second previously-generated uniform random. + if (x != null) y = x, x = null; + + // Otherwise, generate a new x and y. + else do { + x = source() * 2 - 1; + y = source() * 2 - 1; + r = x * x + y * y; + } while (!r || r > 1); + + return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r); + }; + } + + randomNormal.source = sourceRandomNormal; + + return randomNormal; +}))(defaultSource); + +var logNormal = ((function sourceRandomLogNormal(source) { + function randomLogNormal() { + var randomNormal = normal.source(source).apply(this, arguments); + return function() { + return Math.exp(randomNormal()); + }; + } + + randomLogNormal.source = sourceRandomLogNormal; + + return randomLogNormal; +}))(defaultSource); + +var irwinHall = ((function sourceRandomIrwinHall(source) { + function randomIrwinHall(n) { + return function() { + for (var sum = 0, i = 0; i < n; ++i) sum += source(); + return sum; + }; + } + + randomIrwinHall.source = sourceRandomIrwinHall; + + return randomIrwinHall; +}))(defaultSource); + +var bates = ((function sourceRandomBates(source) { + function randomBates(n) { + var randomIrwinHall = irwinHall.source(source)(n); + return function() { + return randomIrwinHall() / n; + }; + } + + randomBates.source = sourceRandomBates; + + return randomBates; +}))(defaultSource); + +var exponential = ((function sourceRandomExponential(source) { + function randomExponential(lambda) { + return function() { + return -Math.log(1 - source()) / lambda; + }; + } + + randomExponential.source = sourceRandomExponential; + + return randomExponential; +}))(defaultSource); + +exports.randomUniform = uniform; +exports.randomNormal = normal; +exports.randomLogNormal = logNormal; +exports.randomBates = bates; +exports.randomIrwinHall = irwinHall; +exports.randomExponential = exponential; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],43:[function(require,module,exports){ +'use strict'; + +var XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var d3Collection = require('d3-collection'); +var d3Dispatch = require('d3-dispatch'); +var d3Dsv = require('d3-dsv'); + +var request = function(url, callback) { + var request, + event = d3Dispatch.dispatch("beforesend", "progress", "load", "error"), + mimeType, + headers = d3Collection.map(), + xhr = new XMLHttpRequest, + user = null, + password = null, + response, + responseType, + timeout = 0; + + // If IE does not support CORS, use XDomainRequest. + if (typeof XDomainRequest !== "undefined" + && !("withCredentials" in xhr) + && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest; + + "onload" in xhr + ? xhr.onload = xhr.onerror = xhr.ontimeout = respond + : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); }; + + function respond(o) { + var status = xhr.status, result; + if (!status && hasResponse(xhr) + || status >= 200 && status < 300 + || status === 304) { + if (response) { + try { + result = response.call(request, xhr); + } catch (e) { + event.call("error", request, e); + return; + } + } else { + result = xhr; + } + event.call("load", request, result); + } else { + event.call("error", request, o); + } + } + + xhr.onprogress = function(e) { + event.call("progress", request, e); + }; + + request = { + header: function(name, value) { + name = (name + "").toLowerCase(); + if (arguments.length < 2) return headers.get(name); + if (value == null) headers.remove(name); + else headers.set(name, value + ""); + return request; + }, + + // If mimeType is non-null and no Accept header is set, a default is used. + mimeType: function(value) { + if (!arguments.length) return mimeType; + mimeType = value == null ? null : value + ""; + return request; + }, + + // Specifies what type the response value should take; + // for instance, arraybuffer, blob, document, or text. + responseType: function(value) { + if (!arguments.length) return responseType; + responseType = value; + return request; + }, + + timeout: function(value) { + if (!arguments.length) return timeout; + timeout = +value; + return request; + }, + + user: function(value) { + return arguments.length < 1 ? user : (user = value == null ? null : value + "", request); + }, + + password: function(value) { + return arguments.length < 1 ? password : (password = value == null ? null : value + "", request); + }, + + // Specify how to convert the response content to a specific type; + // changes the callback value on "load" events. + response: function(value) { + response = value; + return request; + }, + + // Alias for send("GET", …). + get: function(data, callback) { + return request.send("GET", data, callback); + }, + + // Alias for send("POST", …). + post: function(data, callback) { + return request.send("POST", data, callback); + }, + + // If callback is non-null, it will be used for error and load events. + send: function(method, data, callback) { + xhr.open(method, url, true, user, password); + if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*"); + if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); }); + if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType); + if (responseType != null) xhr.responseType = responseType; + if (timeout > 0) xhr.timeout = timeout; + if (callback == null && typeof data === "function") callback = data, data = null; + if (callback != null && callback.length === 1) callback = fixCallback(callback); + if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); }); + event.call("beforesend", request, xhr); + xhr.send(data == null ? null : data); + return request; + }, + + abort: function() { + xhr.abort(); + return request; + }, + + on: function() { + var value = event.on.apply(event, arguments); + return value === event ? request : value; + } + }; + + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return request.get(callback); + } + + return request; +}; + +function fixCallback(callback) { + return function(error, xhr) { + callback(error == null ? xhr : null); + }; +} + +function hasResponse(xhr) { + var type = xhr.responseType; + return type && type !== "text" + ? xhr.response // null on error + : xhr.responseText; // "" on error +} + +var type = function(defaultMimeType, response) { + return function(url, callback) { + var r = request(url).mimeType(defaultMimeType).response(response); + if (callback != null) { + if (typeof callback !== "function") throw new Error("invalid callback: " + callback); + return r.get(callback); + } + return r; + }; +}; + +var html = type("text/html", function(xhr) { + return document.createRange().createContextualFragment(xhr.responseText); +}); + +var json = type("application/json", function(xhr) { + return JSON.parse(xhr.responseText); +}); + +var text = type("text/plain", function(xhr) { + return xhr.responseText; +}); + +var xml = type("application/xml", function(xhr) { + var xml = xhr.responseXML; + if (!xml) throw new Error("parse error"); + return xml; +}); + +var dsv = function(defaultMimeType, parse) { + return function(url, row, callback) { + if (arguments.length < 3) callback = row, row = null; + var r = request(url).mimeType(defaultMimeType); + r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; }; + r.row(row); + return callback ? r.get(callback) : r; + }; +}; + +function responseOf(parse, row) { + return function(request$$1) { + return parse(request$$1.responseText, row); + }; +} + +var csv = dsv("text/csv", d3Dsv.csvParse); + +var tsv = dsv("text/tab-separated-values", d3Dsv.tsvParse); + +exports.request = request; +exports.html = html; +exports.json = json; +exports.text = text; +exports.xml = xml; +exports.csv = csv; +exports.tsv = tsv; + +},{"d3-collection":27,"d3-dispatch":29,"d3-dsv":31,"xmlhttprequest":87}],44:[function(require,module,exports){ +// https://d3js.org/d3-scale/ Version 1.0.7. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-array'), require('d3-collection'), require('d3-interpolate'), require('d3-format'), require('d3-time'), require('d3-time-format'), require('d3-color')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-array', 'd3-collection', 'd3-interpolate', 'd3-format', 'd3-time', 'd3-time-format', 'd3-color'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3,global.d3,global.d3)); +}(this, (function (exports,d3Array,d3Collection,d3Interpolate,d3Format,d3Time,d3TimeFormat,d3Color) { 'use strict'; + +var array = Array.prototype; + +var map$1 = array.map; +var slice = array.slice; + +var implicit = {name: "implicit"}; + +function ordinal(range$$1) { + var index = d3Collection.map(), + domain = [], + unknown = implicit; + + range$$1 = range$$1 == null ? [] : slice.call(range$$1); + + function scale(d) { + var key = d + "", i = index.get(key); + if (!i) { + if (unknown !== implicit) return unknown; + index.set(key, i = domain.push(d)); + } + return range$$1[(i - 1) % range$$1.length]; + } + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = [], index = d3Collection.map(); + var i = -1, n = _.length, d, key; + while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d)); + return scale; + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice.call(_), scale) : range$$1.slice(); + }; + + scale.unknown = function(_) { + return arguments.length ? (unknown = _, scale) : unknown; + }; + + scale.copy = function() { + return ordinal() + .domain(domain) + .range(range$$1) + .unknown(unknown); + }; + + return scale; +} + +function band() { + var scale = ordinal().unknown(undefined), + domain = scale.domain, + ordinalRange = scale.range, + range$$1 = [0, 1], + step, + bandwidth, + round = false, + paddingInner = 0, + paddingOuter = 0, + align = 0.5; + + delete scale.unknown; + + function rescale() { + var n = domain().length, + reverse = range$$1[1] < range$$1[0], + start = range$$1[reverse - 0], + stop = range$$1[1 - reverse]; + step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2); + if (round) step = Math.floor(step); + start += (stop - start - step * (n - paddingInner)) * align; + bandwidth = step * (1 - paddingInner); + if (round) start = Math.round(start), bandwidth = Math.round(bandwidth); + var values = d3Array.range(n).map(function(i) { return start + step * i; }); + return ordinalRange(reverse ? values.reverse() : values); + } + + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice(); + }; + + scale.rangeRound = function(_) { + return range$$1 = [+_[0], +_[1]], round = true, rescale(); + }; + + scale.bandwidth = function() { + return bandwidth; + }; + + scale.step = function() { + return step; + }; + + scale.round = function(_) { + return arguments.length ? (round = !!_, rescale()) : round; + }; + + scale.padding = function(_) { + return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; + + scale.paddingInner = function(_) { + return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner; + }; + + scale.paddingOuter = function(_) { + return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter; + }; + + scale.align = function(_) { + return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align; + }; + + scale.copy = function() { + return band() + .domain(domain()) + .range(range$$1) + .round(round) + .paddingInner(paddingInner) + .paddingOuter(paddingOuter) + .align(align); + }; + + return rescale(); +} + +function pointish(scale) { + var copy = scale.copy; + + scale.padding = scale.paddingOuter; + delete scale.paddingInner; + delete scale.paddingOuter; + + scale.copy = function() { + return pointish(copy()); + }; + + return scale; +} + +function point() { + return pointish(band().paddingInner(1)); +} + +var constant = function(x) { + return function() { + return x; + }; +}; + +var number = function(x) { + return +x; +}; + +var unit = [0, 1]; + +function deinterpolateLinear(a, b) { + return (b -= (a = +a)) + ? function(x) { return (x - a) / b; } + : constant(b); +} + +function deinterpolateClamp(deinterpolate) { + return function(a, b) { + var d = deinterpolate(a = +a, b = +b); + return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); }; + }; +} + +function reinterpolateClamp(reinterpolate) { + return function(a, b) { + var r = reinterpolate(a = +a, b = +b); + return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); }; + }; +} + +function bimap(domain, range$$1, deinterpolate, reinterpolate) { + var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1]; + if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0); + else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1); + return function(x) { return r0(d0(x)); }; +} + +function polymap(domain, range$$1, deinterpolate, reinterpolate) { + var j = Math.min(domain.length, range$$1.length) - 1, + d = new Array(j), + r = new Array(j), + i = -1; + + // Reverse descending domains. + if (domain[j] < domain[0]) { + domain = domain.slice().reverse(); + range$$1 = range$$1.slice().reverse(); + } + + while (++i < j) { + d[i] = deinterpolate(domain[i], domain[i + 1]); + r[i] = reinterpolate(range$$1[i], range$$1[i + 1]); + } + + return function(x) { + var i = d3Array.bisect(domain, x, 1, j) - 1; + return r[i](d[i](x)); + }; +} + +function copy(source, target) { + return target + .domain(source.domain()) + .range(source.range()) + .interpolate(source.interpolate()) + .clamp(source.clamp()); +} + +// deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1]. +// reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b]. +function continuous(deinterpolate, reinterpolate) { + var domain = unit, + range$$1 = unit, + interpolate$$1 = d3Interpolate.interpolate, + clamp = false, + piecewise, + output, + input; + + function rescale() { + piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap; + output = input = null; + return scale; + } + + function scale(x) { + return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x); + } + + scale.invert = function(y) { + return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y); + }; + + scale.domain = function(_) { + return arguments.length ? (domain = map$1.call(_, number), rescale()) : domain.slice(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice.call(_), rescale()) : range$$1.slice(); + }; + + scale.rangeRound = function(_) { + return range$$1 = slice.call(_), interpolate$$1 = d3Interpolate.interpolateRound, rescale(); + }; + + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, rescale()) : clamp; + }; + + scale.interpolate = function(_) { + return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1; + }; + + return rescale(); +} + +var tickFormat = function(domain, count, specifier) { + var start = domain[0], + stop = domain[domain.length - 1], + step = d3Array.tickStep(start, stop, count == null ? 10 : count), + precision; + specifier = d3Format.formatSpecifier(specifier == null ? ",f" : specifier); + switch (specifier.type) { + case "s": { + var value = Math.max(Math.abs(start), Math.abs(stop)); + if (specifier.precision == null && !isNaN(precision = d3Format.precisionPrefix(step, value))) specifier.precision = precision; + return d3Format.formatPrefix(specifier, value); + } + case "": + case "e": + case "g": + case "p": + case "r": { + if (specifier.precision == null && !isNaN(precision = d3Format.precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e"); + break; + } + case "f": + case "%": { + if (specifier.precision == null && !isNaN(precision = d3Format.precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2; + break; + } + } + return d3Format.format(specifier); +}; + +function linearish(scale) { + var domain = scale.domain; + + scale.ticks = function(count) { + var d = domain(); + return d3Array.ticks(d[0], d[d.length - 1], count == null ? 10 : count); + }; + + scale.tickFormat = function(count, specifier) { + return tickFormat(domain(), count, specifier); + }; + + scale.nice = function(count) { + if (count == null) count = 10; + + var d = domain(), + i0 = 0, + i1 = d.length - 1, + start = d[i0], + stop = d[i1], + step; + + if (stop < start) { + step = start, start = stop, stop = step; + step = i0, i0 = i1, i1 = step; + } + + step = d3Array.tickIncrement(start, stop, count); + + if (step > 0) { + start = Math.floor(start / step) * step; + stop = Math.ceil(stop / step) * step; + step = d3Array.tickIncrement(start, stop, count); + } else if (step < 0) { + start = Math.ceil(start * step) / step; + stop = Math.floor(stop * step) / step; + step = d3Array.tickIncrement(start, stop, count); + } + + if (step > 0) { + d[i0] = Math.floor(start / step) * step; + d[i1] = Math.ceil(stop / step) * step; + domain(d); + } else if (step < 0) { + d[i0] = Math.ceil(start * step) / step; + d[i1] = Math.floor(stop * step) / step; + domain(d); + } + + return scale; + }; + + return scale; +} + +function linear() { + var scale = continuous(deinterpolateLinear, d3Interpolate.interpolateNumber); + + scale.copy = function() { + return copy(scale, linear()); + }; + + return linearish(scale); +} + +function identity() { + var domain = [0, 1]; + + function scale(x) { + return +x; + } + + scale.invert = scale; + + scale.domain = scale.range = function(_) { + return arguments.length ? (domain = map$1.call(_, number), scale) : domain.slice(); + }; + + scale.copy = function() { + return identity().domain(domain); + }; + + return linearish(scale); +} + +var nice = function(domain, interval) { + domain = domain.slice(); + + var i0 = 0, + i1 = domain.length - 1, + x0 = domain[i0], + x1 = domain[i1], + t; + + if (x1 < x0) { + t = i0, i0 = i1, i1 = t; + t = x0, x0 = x1, x1 = t; + } + + domain[i0] = interval.floor(x0); + domain[i1] = interval.ceil(x1); + return domain; +}; + +function deinterpolate(a, b) { + return (b = Math.log(b / a)) + ? function(x) { return Math.log(x / a) / b; } + : constant(b); +} + +function reinterpolate(a, b) { + return a < 0 + ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); } + : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); }; +} + +function pow10(x) { + return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x; +} + +function powp(base) { + return base === 10 ? pow10 + : base === Math.E ? Math.exp + : function(x) { return Math.pow(base, x); }; +} + +function logp(base) { + return base === Math.E ? Math.log + : base === 10 && Math.log10 + || base === 2 && Math.log2 + || (base = Math.log(base), function(x) { return Math.log(x) / base; }); +} + +function reflect(f) { + return function(x) { + return -f(-x); + }; +} + +function log() { + var scale = continuous(deinterpolate, reinterpolate).domain([1, 10]), + domain = scale.domain, + base = 10, + logs = logp(10), + pows = powp(10); + + function rescale() { + logs = logp(base), pows = powp(base); + if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows); + return scale; + } + + scale.base = function(_) { + return arguments.length ? (base = +_, rescale()) : base; + }; + + scale.domain = function(_) { + return arguments.length ? (domain(_), rescale()) : domain(); + }; + + scale.ticks = function(count) { + var d = domain(), + u = d[0], + v = d[d.length - 1], + r; + + if (r = v < u) i = u, u = v, v = i; + + var i = logs(u), + j = logs(v), + p, + k, + t, + n = count == null ? 10 : +count, + z = []; + + if (!(base % 1) && j - i < n) { + i = Math.round(i) - 1, j = Math.round(j) + 1; + if (u > 0) for (; i < j; ++i) { + for (k = 1, p = pows(i); k < base; ++k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); + } + } else for (; i < j; ++i) { + for (k = base - 1, p = pows(i); k >= 1; --k) { + t = p * k; + if (t < u) continue; + if (t > v) break; + z.push(t); + } + } + } else { + z = d3Array.ticks(i, j, Math.min(j - i, n)).map(pows); + } + + return r ? z.reverse() : z; + }; + + scale.tickFormat = function(count, specifier) { + if (specifier == null) specifier = base === 10 ? ".0e" : ","; + if (typeof specifier !== "function") specifier = d3Format.format(specifier); + if (count === Infinity) return specifier; + if (count == null) count = 10; + var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate? + return function(d) { + var i = d / pows(Math.round(logs(d))); + if (i * base < base - 0.5) i *= base; + return i <= k ? specifier(d) : ""; + }; + }; + + scale.nice = function() { + return domain(nice(domain(), { + floor: function(x) { return pows(Math.floor(logs(x))); }, + ceil: function(x) { return pows(Math.ceil(logs(x))); } + })); + }; + + scale.copy = function() { + return copy(scale, log().base(base)); + }; + + return scale; +} + +function raise(x, exponent) { + return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent); +} + +function pow() { + var exponent = 1, + scale = continuous(deinterpolate, reinterpolate), + domain = scale.domain; + + function deinterpolate(a, b) { + return (b = raise(b, exponent) - (a = raise(a, exponent))) + ? function(x) { return (raise(x, exponent) - a) / b; } + : constant(b); + } + + function reinterpolate(a, b) { + b = raise(b, exponent) - (a = raise(a, exponent)); + return function(t) { return raise(a + b * t, 1 / exponent); }; + } + + scale.exponent = function(_) { + return arguments.length ? (exponent = +_, domain(domain())) : exponent; + }; + + scale.copy = function() { + return copy(scale, pow().exponent(exponent)); + }; + + return linearish(scale); +} + +function sqrt() { + return pow().exponent(0.5); +} + +function quantile$1() { + var domain = [], + range$$1 = [], + thresholds = []; + + function rescale() { + var i = 0, n = Math.max(1, range$$1.length); + thresholds = new Array(n - 1); + while (++i < n) thresholds[i - 1] = d3Array.quantile(domain, i / n); + return scale; + } + + function scale(x) { + if (!isNaN(x = +x)) return range$$1[d3Array.bisect(thresholds, x)]; + } + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] : [ + i > 0 ? thresholds[i - 1] : domain[0], + i < thresholds.length ? thresholds[i] : domain[domain.length - 1] + ]; + }; + + scale.domain = function(_) { + if (!arguments.length) return domain.slice(); + domain = []; + for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d); + domain.sort(d3Array.ascending); + return rescale(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice.call(_), rescale()) : range$$1.slice(); + }; + + scale.quantiles = function() { + return thresholds.slice(); + }; + + scale.copy = function() { + return quantile$1() + .domain(domain) + .range(range$$1); + }; + + return scale; +} + +function quantize() { + var x0 = 0, + x1 = 1, + n = 1, + domain = [0.5], + range$$1 = [0, 1]; + + function scale(x) { + if (x <= x) return range$$1[d3Array.bisect(domain, x, 0, n)]; + } + + function rescale() { + var i = -1; + domain = new Array(n); + while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1); + return scale; + } + + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1]; + }; + + scale.range = function(_) { + return arguments.length ? (n = (range$$1 = slice.call(_)).length - 1, rescale()) : range$$1.slice(); + }; + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return i < 0 ? [NaN, NaN] + : i < 1 ? [x0, domain[0]] + : i >= n ? [domain[n - 1], x1] + : [domain[i - 1], domain[i]]; + }; + + scale.copy = function() { + return quantize() + .domain([x0, x1]) + .range(range$$1); + }; + + return linearish(scale); +} + +function threshold() { + var domain = [0.5], + range$$1 = [0, 1], + n = 1; + + function scale(x) { + if (x <= x) return range$$1[d3Array.bisect(domain, x, 0, n)]; + } + + scale.domain = function(_) { + return arguments.length ? (domain = slice.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice(); + }; + + scale.range = function(_) { + return arguments.length ? (range$$1 = slice.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice(); + }; + + scale.invertExtent = function(y) { + var i = range$$1.indexOf(y); + return [domain[i - 1], domain[i]]; + }; + + scale.copy = function() { + return threshold() + .domain(domain) + .range(range$$1); + }; + + return scale; +} + +var durationSecond = 1000; +var durationMinute = durationSecond * 60; +var durationHour = durationMinute * 60; +var durationDay = durationHour * 24; +var durationWeek = durationDay * 7; +var durationMonth = durationDay * 30; +var durationYear = durationDay * 365; + +function date(t) { + return new Date(t); +} + +function number$1(t) { + return t instanceof Date ? +t : +new Date(+t); +} + +function calendar(year, month, week, day, hour, minute, second, millisecond, format$$1) { + var scale = continuous(deinterpolateLinear, d3Interpolate.interpolateNumber), + invert = scale.invert, + domain = scale.domain; + + var formatMillisecond = format$$1(".%L"), + formatSecond = format$$1(":%S"), + formatMinute = format$$1("%I:%M"), + formatHour = format$$1("%I %p"), + formatDay = format$$1("%a %d"), + formatWeek = format$$1("%b %d"), + formatMonth = format$$1("%B"), + formatYear = format$$1("%Y"); + + var tickIntervals = [ + [second, 1, durationSecond], + [second, 5, 5 * durationSecond], + [second, 15, 15 * durationSecond], + [second, 30, 30 * durationSecond], + [minute, 1, durationMinute], + [minute, 5, 5 * durationMinute], + [minute, 15, 15 * durationMinute], + [minute, 30, 30 * durationMinute], + [ hour, 1, durationHour ], + [ hour, 3, 3 * durationHour ], + [ hour, 6, 6 * durationHour ], + [ hour, 12, 12 * durationHour ], + [ day, 1, durationDay ], + [ day, 2, 2 * durationDay ], + [ week, 1, durationWeek ], + [ month, 1, durationMonth ], + [ month, 3, 3 * durationMonth ], + [ year, 1, durationYear ] + ]; + + function tickFormat(date) { + return (second(date) < date ? formatMillisecond + : minute(date) < date ? formatSecond + : hour(date) < date ? formatMinute + : day(date) < date ? formatHour + : month(date) < date ? (week(date) < date ? formatDay : formatWeek) + : year(date) < date ? formatMonth + : formatYear)(date); + } + + function tickInterval(interval, start, stop, step) { + if (interval == null) interval = 10; + + // If a desired tick count is specified, pick a reasonable tick interval + // based on the extent of the domain and a rough estimate of tick size. + // Otherwise, assume interval is already a time interval and use it. + if (typeof interval === "number") { + var target = Math.abs(stop - start) / interval, + i = d3Array.bisector(function(i) { return i[2]; }).right(tickIntervals, target); + if (i === tickIntervals.length) { + step = d3Array.tickStep(start / durationYear, stop / durationYear, interval); + interval = year; + } else if (i) { + i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i]; + step = i[1]; + interval = i[0]; + } else { + step = Math.max(d3Array.tickStep(start, stop, interval), 1); + interval = millisecond; + } + } + + return step == null ? interval : interval.every(step); + } + + scale.invert = function(y) { + return new Date(invert(y)); + }; + + scale.domain = function(_) { + return arguments.length ? domain(map$1.call(_, number$1)) : domain().map(date); + }; + + scale.ticks = function(interval, step) { + var d = domain(), + t0 = d[0], + t1 = d[d.length - 1], + r = t1 < t0, + t; + if (r) t = t0, t0 = t1, t1 = t; + t = tickInterval(interval, t0, t1, step); + t = t ? t.range(t0, t1 + 1) : []; // inclusive stop + return r ? t.reverse() : t; + }; + + scale.tickFormat = function(count, specifier) { + return specifier == null ? tickFormat : format$$1(specifier); + }; + + scale.nice = function(interval, step) { + var d = domain(); + return (interval = tickInterval(interval, d[0], d[d.length - 1], step)) + ? domain(nice(d, interval)) + : scale; + }; + + scale.copy = function() { + return copy(scale, calendar(year, month, week, day, hour, minute, second, millisecond, format$$1)); + }; + + return scale; +} + +var time = function() { + return calendar(d3Time.timeYear, d3Time.timeMonth, d3Time.timeWeek, d3Time.timeDay, d3Time.timeHour, d3Time.timeMinute, d3Time.timeSecond, d3Time.timeMillisecond, d3TimeFormat.timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]); +}; + +var utcTime = function() { + return calendar(d3Time.utcYear, d3Time.utcMonth, d3Time.utcWeek, d3Time.utcDay, d3Time.utcHour, d3Time.utcMinute, d3Time.utcSecond, d3Time.utcMillisecond, d3TimeFormat.utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]); +}; + +var colors = function(s) { + return s.match(/.{6}/g).map(function(x) { + return "#" + x; + }); +}; + +var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf"); + +var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6"); + +var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9"); + +var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5"); + +var cubehelix$1 = d3Interpolate.interpolateCubehelixLong(d3Color.cubehelix(300, 0.5, 0.0), d3Color.cubehelix(-240, 0.5, 1.0)); + +var warm = d3Interpolate.interpolateCubehelixLong(d3Color.cubehelix(-100, 0.75, 0.35), d3Color.cubehelix(80, 1.50, 0.8)); + +var cool = d3Interpolate.interpolateCubehelixLong(d3Color.cubehelix(260, 0.75, 0.35), d3Color.cubehelix(80, 1.50, 0.8)); + +var rainbow = d3Color.cubehelix(); + +var rainbow$1 = function(t) { + if (t < 0 || t > 1) t -= Math.floor(t); + var ts = Math.abs(t - 0.5); + rainbow.h = 360 * t - 100; + rainbow.s = 1.5 - 1.5 * ts; + rainbow.l = 0.8 - 0.9 * ts; + return rainbow + ""; +}; + +function ramp(range$$1) { + var n = range$$1.length; + return function(t) { + return range$$1[Math.max(0, Math.min(n - 1, Math.floor(t * n)))]; + }; +} + +var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725")); + +var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf")); + +var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4")); + +var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921")); + +function sequential(interpolator) { + var x0 = 0, + x1 = 1, + clamp = false; + + function scale(x) { + var t = (x - x0) / (x1 - x0); + return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t); + } + + scale.domain = function(_) { + return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1]; + }; + + scale.clamp = function(_) { + return arguments.length ? (clamp = !!_, scale) : clamp; + }; + + scale.interpolator = function(_) { + return arguments.length ? (interpolator = _, scale) : interpolator; + }; + + scale.copy = function() { + return sequential(interpolator).domain([x0, x1]).clamp(clamp); + }; + + return linearish(scale); +} + +exports.scaleBand = band; +exports.scalePoint = point; +exports.scaleIdentity = identity; +exports.scaleLinear = linear; +exports.scaleLog = log; +exports.scaleOrdinal = ordinal; +exports.scaleImplicit = implicit; +exports.scalePow = pow; +exports.scaleSqrt = sqrt; +exports.scaleQuantile = quantile$1; +exports.scaleQuantize = quantize; +exports.scaleThreshold = threshold; +exports.scaleTime = time; +exports.scaleUtc = utcTime; +exports.schemeCategory10 = category10; +exports.schemeCategory20b = category20b; +exports.schemeCategory20c = category20c; +exports.schemeCategory20 = category20; +exports.interpolateCubehelixDefault = cubehelix$1; +exports.interpolateRainbow = rainbow$1; +exports.interpolateWarm = warm; +exports.interpolateCool = cool; +exports.interpolateViridis = viridis; +exports.interpolateMagma = magma; +exports.interpolateInferno = inferno; +exports.interpolatePlasma = plasma; +exports.scaleSequential = sequential; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-array":23,"d3-collection":27,"d3-color":28,"d3-format":34,"d3-interpolate":37,"d3-time":48,"d3-time-format":47}],45:[function(require,module,exports){ +// https://d3js.org/d3-selection/ Version 1.3.0. Copyright 2018 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var xhtml = "http://www.w3.org/1999/xhtml"; + +var namespaces = { + svg: "http://www.w3.org/2000/svg", + xhtml: xhtml, + xlink: "http://www.w3.org/1999/xlink", + xml: "http://www.w3.org/XML/1998/namespace", + xmlns: "http://www.w3.org/2000/xmlns/" +}; + +function namespace(name) { + var prefix = name += "", i = prefix.indexOf(":"); + if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1); + return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name; +} + +function creatorInherit(name) { + return function() { + var document = this.ownerDocument, + uri = this.namespaceURI; + return uri === xhtml && document.documentElement.namespaceURI === xhtml + ? document.createElement(name) + : document.createElementNS(uri, name); + }; +} + +function creatorFixed(fullname) { + return function() { + return this.ownerDocument.createElementNS(fullname.space, fullname.local); + }; +} + +function creator(name) { + var fullname = namespace(name); + return (fullname.local + ? creatorFixed + : creatorInherit)(fullname); +} + +function none() {} + +function selector(selector) { + return selector == null ? none : function() { + return this.querySelector(selector); + }; +} + +function selection_select(select) { + if (typeof select !== "function") select = selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + } + } + } + + return new Selection(subgroups, this._parents); +} + +function empty() { + return []; +} + +function selectorAll(selector) { + return selector == null ? empty : function() { + return this.querySelectorAll(selector); + }; +} + +function selection_selectAll(select) { + if (typeof select !== "function") select = selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + subgroups.push(select.call(node, node.__data__, i, group)); + parents.push(node); + } + } + } + + return new Selection(subgroups, parents); +} + +var matcher = function(selector) { + return function() { + return this.matches(selector); + }; +}; + +if (typeof document !== "undefined") { + var element = document.documentElement; + if (!element.matches) { + var vendorMatches = element.webkitMatchesSelector + || element.msMatchesSelector + || element.mozMatchesSelector + || element.oMatchesSelector; + matcher = function(selector) { + return function() { + return vendorMatches.call(this, selector); + }; + }; + } +} + +var matcher$1 = matcher; + +function selection_filter(match) { + if (typeof match !== "function") match = matcher$1(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Selection(subgroups, this._parents); +} + +function sparse(update) { + return new Array(update.length); +} + +function selection_enter() { + return new Selection(this._enter || this._groups.map(sparse), this._parents); +} + +function EnterNode(parent, datum) { + this.ownerDocument = parent.ownerDocument; + this.namespaceURI = parent.namespaceURI; + this._next = null; + this._parent = parent; + this.__data__ = datum; +} + +EnterNode.prototype = { + constructor: EnterNode, + appendChild: function(child) { return this._parent.insertBefore(child, this._next); }, + insertBefore: function(child, next) { return this._parent.insertBefore(child, next); }, + querySelector: function(selector) { return this._parent.querySelector(selector); }, + querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); } +}; + +function constant(x) { + return function() { + return x; + }; +} + +var keyPrefix = "$"; // Protect against keys like “__proto__”. + +function bindIndex(parent, group, enter, update, exit, data) { + var i = 0, + node, + groupLength = group.length, + dataLength = data.length; + + // Put any non-null nodes that fit into update. + // Put any null nodes into enter. + // Put any remaining data into enter. + for (; i < dataLength; ++i) { + if (node = group[i]) { + node.__data__ = data[i]; + update[i] = node; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Put any non-null nodes that don’t fit into exit. + for (; i < groupLength; ++i) { + if (node = group[i]) { + exit[i] = node; + } + } +} + +function bindKey(parent, group, enter, update, exit, data, key) { + var i, + node, + nodeByKeyValue = {}, + groupLength = group.length, + dataLength = data.length, + keyValues = new Array(groupLength), + keyValue; + + // Compute the key for each node. + // If multiple nodes have the same key, the duplicates are added to exit. + for (i = 0; i < groupLength; ++i) { + if (node = group[i]) { + keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group); + if (keyValue in nodeByKeyValue) { + exit[i] = node; + } else { + nodeByKeyValue[keyValue] = node; + } + } + } + + // Compute the key for each datum. + // If there a node associated with this key, join and add it to update. + // If there is not (or the key is a duplicate), add it to enter. + for (i = 0; i < dataLength; ++i) { + keyValue = keyPrefix + key.call(parent, data[i], i, data); + if (node = nodeByKeyValue[keyValue]) { + update[i] = node; + node.__data__ = data[i]; + nodeByKeyValue[keyValue] = null; + } else { + enter[i] = new EnterNode(parent, data[i]); + } + } + + // Add any remaining nodes that were not bound to data to exit. + for (i = 0; i < groupLength; ++i) { + if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) { + exit[i] = node; + } + } +} + +function selection_data(value, key) { + if (!value) { + data = new Array(this.size()), j = -1; + this.each(function(d) { data[++j] = d; }); + return data; + } + + var bind = key ? bindKey : bindIndex, + parents = this._parents, + groups = this._groups; + + if (typeof value !== "function") value = constant(value); + + for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) { + var parent = parents[j], + group = groups[j], + groupLength = group.length, + data = value.call(parent, parent && parent.__data__, j, parents), + dataLength = data.length, + enterGroup = enter[j] = new Array(dataLength), + updateGroup = update[j] = new Array(dataLength), + exitGroup = exit[j] = new Array(groupLength); + + bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); + + // Now connect the enter nodes to their following update node, such that + // appendChild can insert the materialized enter node before this node, + // rather than at the end of the parent node. + for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) { + if (previous = enterGroup[i0]) { + if (i0 >= i1) i1 = i0 + 1; + while (!(next = updateGroup[i1]) && ++i1 < dataLength); + previous._next = next || null; + } + } + } + + update = new Selection(update, parents); + update._enter = enter; + update._exit = exit; + return update; +} + +function selection_exit() { + return new Selection(this._exit || this._groups.map(sparse), this._parents); +} + +function selection_merge(selection$$1) { + + for (var groups0 = this._groups, groups1 = selection$$1._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Selection(merges, this._parents); +} + +function selection_order() { + + for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) { + for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) { + if (node = group[i]) { + if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next); + next = node; + } + } + } + + return this; +} + +function selection_sort(compare) { + if (!compare) compare = ascending; + + function compareNode(a, b) { + return a && b ? compare(a.__data__, b.__data__) : !a - !b; + } + + for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group[i]) { + sortgroup[i] = node; + } + } + sortgroup.sort(compareNode); + } + + return new Selection(sortgroups, this._parents).order(); +} + +function ascending(a, b) { + return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN; +} + +function selection_call() { + var callback = arguments[0]; + arguments[0] = this; + callback.apply(null, arguments); + return this; +} + +function selection_nodes() { + var nodes = new Array(this.size()), i = -1; + this.each(function() { nodes[++i] = this; }); + return nodes; +} + +function selection_node() { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length; i < n; ++i) { + var node = group[i]; + if (node) return node; + } + } + + return null; +} + +function selection_size() { + var size = 0; + this.each(function() { ++size; }); + return size; +} + +function selection_empty() { + return !this.node(); +} + +function selection_each(callback) { + + for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) { + for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) { + if (node = group[i]) callback.call(node, node.__data__, i, group); + } + } + + return this; +} + +function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; +} + +function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; +} + +function attrConstant(name, value) { + return function() { + this.setAttribute(name, value); + }; +} + +function attrConstantNS(fullname, value) { + return function() { + this.setAttributeNS(fullname.space, fullname.local, value); + }; +} + +function attrFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttribute(name); + else this.setAttribute(name, v); + }; +} + +function attrFunctionNS(fullname, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.removeAttributeNS(fullname.space, fullname.local); + else this.setAttributeNS(fullname.space, fullname.local, v); + }; +} + +function selection_attr(name, value) { + var fullname = namespace(name); + + if (arguments.length < 2) { + var node = this.node(); + return fullname.local + ? node.getAttributeNS(fullname.space, fullname.local) + : node.getAttribute(fullname); + } + + return this.each((value == null + ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function" + ? (fullname.local ? attrFunctionNS : attrFunction) + : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value)); +} + +function defaultView(node) { + return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node + || (node.document && node) // node is a Window + || node.defaultView; // node is a Document +} + +function styleRemove(name) { + return function() { + this.style.removeProperty(name); + }; +} + +function styleConstant(name, value, priority) { + return function() { + this.style.setProperty(name, value, priority); + }; +} + +function styleFunction(name, value, priority) { + return function() { + var v = value.apply(this, arguments); + if (v == null) this.style.removeProperty(name); + else this.style.setProperty(name, v, priority); + }; +} + +function selection_style(name, value, priority) { + return arguments.length > 1 + ? this.each((value == null + ? styleRemove : typeof value === "function" + ? styleFunction + : styleConstant)(name, value, priority == null ? "" : priority)) + : styleValue(this.node(), name); +} + +function styleValue(node, name) { + return node.style.getPropertyValue(name) + || defaultView(node).getComputedStyle(node, null).getPropertyValue(name); +} + +function propertyRemove(name) { + return function() { + delete this[name]; + }; +} + +function propertyConstant(name, value) { + return function() { + this[name] = value; + }; +} + +function propertyFunction(name, value) { + return function() { + var v = value.apply(this, arguments); + if (v == null) delete this[name]; + else this[name] = v; + }; +} + +function selection_property(name, value) { + return arguments.length > 1 + ? this.each((value == null + ? propertyRemove : typeof value === "function" + ? propertyFunction + : propertyConstant)(name, value)) + : this.node()[name]; +} + +function classArray(string) { + return string.trim().split(/^|\s+/); +} + +function classList(node) { + return node.classList || new ClassList(node); +} + +function ClassList(node) { + this._node = node; + this._names = classArray(node.getAttribute("class") || ""); +} + +ClassList.prototype = { + add: function(name) { + var i = this._names.indexOf(name); + if (i < 0) { + this._names.push(name); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + remove: function(name) { + var i = this._names.indexOf(name); + if (i >= 0) { + this._names.splice(i, 1); + this._node.setAttribute("class", this._names.join(" ")); + } + }, + contains: function(name) { + return this._names.indexOf(name) >= 0; + } +}; + +function classedAdd(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.add(names[i]); +} + +function classedRemove(node, names) { + var list = classList(node), i = -1, n = names.length; + while (++i < n) list.remove(names[i]); +} + +function classedTrue(names) { + return function() { + classedAdd(this, names); + }; +} + +function classedFalse(names) { + return function() { + classedRemove(this, names); + }; +} + +function classedFunction(names, value) { + return function() { + (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names); + }; +} + +function selection_classed(name, value) { + var names = classArray(name + ""); + + if (arguments.length < 2) { + var list = classList(this.node()), i = -1, n = names.length; + while (++i < n) if (!list.contains(names[i])) return false; + return true; + } + + return this.each((typeof value === "function" + ? classedFunction : value + ? classedTrue + : classedFalse)(names, value)); +} + +function textRemove() { + this.textContent = ""; +} + +function textConstant(value) { + return function() { + this.textContent = value; + }; +} + +function textFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.textContent = v == null ? "" : v; + }; +} + +function selection_text(value) { + return arguments.length + ? this.each(value == null + ? textRemove : (typeof value === "function" + ? textFunction + : textConstant)(value)) + : this.node().textContent; +} + +function htmlRemove() { + this.innerHTML = ""; +} + +function htmlConstant(value) { + return function() { + this.innerHTML = value; + }; +} + +function htmlFunction(value) { + return function() { + var v = value.apply(this, arguments); + this.innerHTML = v == null ? "" : v; + }; +} + +function selection_html(value) { + return arguments.length + ? this.each(value == null + ? htmlRemove : (typeof value === "function" + ? htmlFunction + : htmlConstant)(value)) + : this.node().innerHTML; +} + +function raise() { + if (this.nextSibling) this.parentNode.appendChild(this); +} + +function selection_raise() { + return this.each(raise); +} + +function lower() { + if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild); +} + +function selection_lower() { + return this.each(lower); +} + +function selection_append(name) { + var create = typeof name === "function" ? name : creator(name); + return this.select(function() { + return this.appendChild(create.apply(this, arguments)); + }); +} + +function constantNull() { + return null; +} + +function selection_insert(name, before) { + var create = typeof name === "function" ? name : creator(name), + select = before == null ? constantNull : typeof before === "function" ? before : selector(before); + return this.select(function() { + return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null); + }); +} + +function remove() { + var parent = this.parentNode; + if (parent) parent.removeChild(this); +} + +function selection_remove() { + return this.each(remove); +} + +function selection_cloneShallow() { + return this.parentNode.insertBefore(this.cloneNode(false), this.nextSibling); +} + +function selection_cloneDeep() { + return this.parentNode.insertBefore(this.cloneNode(true), this.nextSibling); +} + +function selection_clone(deep) { + return this.select(deep ? selection_cloneDeep : selection_cloneShallow); +} + +function selection_datum(value) { + return arguments.length + ? this.property("__data__", value) + : this.node().__data__; +} + +var filterEvents = {}; + +exports.event = null; + +if (typeof document !== "undefined") { + var element$1 = document.documentElement; + if (!("onmouseenter" in element$1)) { + filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"}; + } +} + +function filterContextListener(listener, index, group) { + listener = contextListener(listener, index, group); + return function(event) { + var related = event.relatedTarget; + if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) { + listener.call(this, event); + } + }; +} + +function contextListener(listener, index, group) { + return function(event1) { + var event0 = exports.event; // Events can be reentrant (e.g., focus). + exports.event = event1; + try { + listener.call(this, this.__data__, index, group); + } finally { + exports.event = event0; + } + }; +} + +function parseTypenames(typenames) { + return typenames.trim().split(/^|\s+/).map(function(t) { + var name = "", i = t.indexOf("."); + if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i); + return {type: t, name: name}; + }); +} + +function onRemove(typename) { + return function() { + var on = this.__on; + if (!on) return; + for (var j = 0, i = -1, m = on.length, o; j < m; ++j) { + if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + } else { + on[++i] = o; + } + } + if (++i) on.length = i; + else delete this.__on; + }; +} + +function onAdd(typename, value, capture) { + var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener; + return function(d, i, group) { + var on = this.__on, o, listener = wrap(value, i, group); + if (on) for (var j = 0, m = on.length; j < m; ++j) { + if ((o = on[j]).type === typename.type && o.name === typename.name) { + this.removeEventListener(o.type, o.listener, o.capture); + this.addEventListener(o.type, o.listener = listener, o.capture = capture); + o.value = value; + return; + } + } + this.addEventListener(typename.type, listener, capture); + o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture}; + if (!on) this.__on = [o]; + else on.push(o); + }; +} + +function selection_on(typename, value, capture) { + var typenames = parseTypenames(typename + ""), i, n = typenames.length, t; + + if (arguments.length < 2) { + var on = this.node().__on; + if (on) for (var j = 0, m = on.length, o; j < m; ++j) { + for (i = 0, o = on[j]; i < n; ++i) { + if ((t = typenames[i]).type === o.type && t.name === o.name) { + return o.value; + } + } + } + return; + } + + on = value ? onAdd : onRemove; + if (capture == null) capture = false; + for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture)); + return this; +} + +function customEvent(event1, listener, that, args) { + var event0 = exports.event; + event1.sourceEvent = exports.event; + exports.event = event1; + try { + return listener.apply(that, args); + } finally { + exports.event = event0; + } +} + +function dispatchEvent(node, type, params) { + var window = defaultView(node), + event = window.CustomEvent; + + if (typeof event === "function") { + event = new event(type, params); + } else { + event = window.document.createEvent("Event"); + if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail; + else event.initEvent(type, false, false); + } + + node.dispatchEvent(event); +} + +function dispatchConstant(type, params) { + return function() { + return dispatchEvent(this, type, params); + }; +} + +function dispatchFunction(type, params) { + return function() { + return dispatchEvent(this, type, params.apply(this, arguments)); + }; +} + +function selection_dispatch(type, params) { + return this.each((typeof params === "function" + ? dispatchFunction + : dispatchConstant)(type, params)); +} + +var root = [null]; + +function Selection(groups, parents) { + this._groups = groups; + this._parents = parents; +} + +function selection() { + return new Selection([[document.documentElement]], root); +} + +Selection.prototype = selection.prototype = { + constructor: Selection, + select: selection_select, + selectAll: selection_selectAll, + filter: selection_filter, + data: selection_data, + enter: selection_enter, + exit: selection_exit, + merge: selection_merge, + order: selection_order, + sort: selection_sort, + call: selection_call, + nodes: selection_nodes, + node: selection_node, + size: selection_size, + empty: selection_empty, + each: selection_each, + attr: selection_attr, + style: selection_style, + property: selection_property, + classed: selection_classed, + text: selection_text, + html: selection_html, + raise: selection_raise, + lower: selection_lower, + append: selection_append, + insert: selection_insert, + remove: selection_remove, + clone: selection_clone, + datum: selection_datum, + on: selection_on, + dispatch: selection_dispatch +}; + +function select(selector) { + return typeof selector === "string" + ? new Selection([[document.querySelector(selector)]], [document.documentElement]) + : new Selection([[selector]], root); +} + +function create(name) { + return select(creator(name).call(document.documentElement)); +} + +var nextId = 0; + +function local() { + return new Local; +} + +function Local() { + this._ = "@" + (++nextId).toString(36); +} + +Local.prototype = local.prototype = { + constructor: Local, + get: function(node) { + var id = this._; + while (!(id in node)) if (!(node = node.parentNode)) return; + return node[id]; + }, + set: function(node, value) { + return node[this._] = value; + }, + remove: function(node) { + return this._ in node && delete node[this._]; + }, + toString: function() { + return this._; + } +}; + +function sourceEvent() { + var current = exports.event, source; + while (source = current.sourceEvent) current = source; + return current; +} + +function point(node, event) { + var svg = node.ownerSVGElement || node; + + if (svg.createSVGPoint) { + var point = svg.createSVGPoint(); + point.x = event.clientX, point.y = event.clientY; + point = point.matrixTransform(node.getScreenCTM().inverse()); + return [point.x, point.y]; + } + + var rect = node.getBoundingClientRect(); + return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop]; +} + +function mouse(node) { + var event = sourceEvent(); + if (event.changedTouches) event = event.changedTouches[0]; + return point(node, event); +} + +function selectAll(selector) { + return typeof selector === "string" + ? new Selection([document.querySelectorAll(selector)], [document.documentElement]) + : new Selection([selector == null ? [] : selector], root); +} + +function touch(node, touches, identifier) { + if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches; + + for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) { + if ((touch = touches[i]).identifier === identifier) { + return point(node, touch); + } + } + + return null; +} + +function touches(node, touches) { + if (touches == null) touches = sourceEvent().touches; + + for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) { + points[i] = point(node, touches[i]); + } + + return points; +} + +exports.create = create; +exports.creator = creator; +exports.local = local; +exports.matcher = matcher$1; +exports.mouse = mouse; +exports.namespace = namespace; +exports.namespaces = namespaces; +exports.clientPoint = point; +exports.select = select; +exports.selectAll = selectAll; +exports.selection = selection; +exports.selector = selector; +exports.selectorAll = selectorAll; +exports.style = styleValue; +exports.touch = touch; +exports.touches = touches; +exports.window = defaultView; +exports.customEvent = customEvent; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],46:[function(require,module,exports){ +// https://d3js.org/d3-shape/ Version 1.2.0. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-path')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-path'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3)); +}(this, (function (exports,d3Path) { 'use strict'; + +var constant = function(x) { + return function constant() { + return x; + }; +}; + +var abs = Math.abs; +var atan2 = Math.atan2; +var cos = Math.cos; +var max = Math.max; +var min = Math.min; +var sin = Math.sin; +var sqrt = Math.sqrt; + +var epsilon = 1e-12; +var pi = Math.PI; +var halfPi = pi / 2; +var tau = 2 * pi; + +function acos(x) { + return x > 1 ? 0 : x < -1 ? pi : Math.acos(x); +} + +function asin(x) { + return x >= 1 ? halfPi : x <= -1 ? -halfPi : Math.asin(x); +} + +function arcInnerRadius(d) { + return d.innerRadius; +} + +function arcOuterRadius(d) { + return d.outerRadius; +} + +function arcStartAngle(d) { + return d.startAngle; +} + +function arcEndAngle(d) { + return d.endAngle; +} + +function arcPadAngle(d) { + return d && d.padAngle; // Note: optional! +} + +function intersect(x0, y0, x1, y1, x2, y2, x3, y3) { + var x10 = x1 - x0, y10 = y1 - y0, + x32 = x3 - x2, y32 = y3 - y2, + t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10); + return [x0 + t * x10, y0 + t * y10]; +} + +// Compute perpendicular offset line of length rc. +// http://mathworld.wolfram.com/Circle-LineIntersection.html +function cornerTangents(x0, y0, x1, y1, r1, rc, cw) { + var x01 = x0 - x1, + y01 = y0 - y1, + lo = (cw ? rc : -rc) / sqrt(x01 * x01 + y01 * y01), + ox = lo * y01, + oy = -lo * x01, + x11 = x0 + ox, + y11 = y0 + oy, + x10 = x1 + ox, + y10 = y1 + oy, + x00 = (x11 + x10) / 2, + y00 = (y11 + y10) / 2, + dx = x10 - x11, + dy = y10 - y11, + d2 = dx * dx + dy * dy, + r = r1 - rc, + D = x11 * y10 - x10 * y11, + d = (dy < 0 ? -1 : 1) * sqrt(max(0, r * r * d2 - D * D)), + cx0 = (D * dy - dx * d) / d2, + cy0 = (-D * dx - dy * d) / d2, + cx1 = (D * dy + dx * d) / d2, + cy1 = (-D * dx + dy * d) / d2, + dx0 = cx0 - x00, + dy0 = cy0 - y00, + dx1 = cx1 - x00, + dy1 = cy1 - y00; + + // Pick the closer of the two intersection points. + // TODO Is there a faster way to determine which intersection to use? + if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1; + + return { + cx: cx0, + cy: cy0, + x01: -ox, + y01: -oy, + x11: cx0 * (r1 / r - 1), + y11: cy0 * (r1 / r - 1) + }; +} + +var arc = function() { + var innerRadius = arcInnerRadius, + outerRadius = arcOuterRadius, + cornerRadius = constant(0), + padRadius = null, + startAngle = arcStartAngle, + endAngle = arcEndAngle, + padAngle = arcPadAngle, + context = null; + + function arc() { + var buffer, + r, + r0 = +innerRadius.apply(this, arguments), + r1 = +outerRadius.apply(this, arguments), + a0 = startAngle.apply(this, arguments) - halfPi, + a1 = endAngle.apply(this, arguments) - halfPi, + da = abs(a1 - a0), + cw = a1 > a0; + + if (!context) context = buffer = d3Path.path(); + + // Ensure that the outer radius is always larger than the inner radius. + if (r1 < r0) r = r1, r1 = r0, r0 = r; + + // Is it a point? + if (!(r1 > epsilon)) context.moveTo(0, 0); + + // Or is it a circle or annulus? + else if (da > tau - epsilon) { + context.moveTo(r1 * cos(a0), r1 * sin(a0)); + context.arc(0, 0, r1, a0, a1, !cw); + if (r0 > epsilon) { + context.moveTo(r0 * cos(a1), r0 * sin(a1)); + context.arc(0, 0, r0, a1, a0, cw); + } + } + + // Or is it a circular or annular sector? + else { + var a01 = a0, + a11 = a1, + a00 = a0, + a10 = a1, + da0 = da, + da1 = da, + ap = padAngle.apply(this, arguments) / 2, + rp = (ap > epsilon) && (padRadius ? +padRadius.apply(this, arguments) : sqrt(r0 * r0 + r1 * r1)), + rc = min(abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)), + rc0 = rc, + rc1 = rc, + t0, + t1; + + // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0. + if (rp > epsilon) { + var p0 = asin(rp / r0 * sin(ap)), + p1 = asin(rp / r1 * sin(ap)); + if ((da0 -= p0 * 2) > epsilon) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0; + else da0 = 0, a00 = a10 = (a0 + a1) / 2; + if ((da1 -= p1 * 2) > epsilon) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1; + else da1 = 0, a01 = a11 = (a0 + a1) / 2; + } + + var x01 = r1 * cos(a01), + y01 = r1 * sin(a01), + x10 = r0 * cos(a10), + y10 = r0 * sin(a10); + + // Apply rounded corners? + if (rc > epsilon) { + var x11 = r1 * cos(a11), + y11 = r1 * sin(a11), + x00 = r0 * cos(a00), + y00 = r0 * sin(a00); + + // Restrict the corner radius according to the sector angle. + if (da < pi) { + var oc = da0 > epsilon ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10], + ax = x01 - oc[0], + ay = y01 - oc[1], + bx = x11 - oc[0], + by = y11 - oc[1], + kc = 1 / sin(acos((ax * bx + ay * by) / (sqrt(ax * ax + ay * ay) * sqrt(bx * bx + by * by))) / 2), + lc = sqrt(oc[0] * oc[0] + oc[1] * oc[1]); + rc0 = min(rc, (r0 - lc) / (kc - 1)); + rc1 = min(rc, (r1 - lc) / (kc + 1)); + } + } + + // Is the sector collapsed to a line? + if (!(da1 > epsilon)) context.moveTo(x01, y01); + + // Does the sector’s outer ring have rounded corners? + else if (rc1 > epsilon) { + t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw); + t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw); + + context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc1, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); + context.arc(0, 0, r1, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw); + context.arc(t1.cx, t1.cy, rc1, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); + } + } + + // Or is the outer ring just a circular arc? + else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw); + + // Is there no inner ring, and it’s a circular sector? + // Or perhaps it’s an annular sector collapsed due to padding? + if (!(r0 > epsilon) || !(da0 > epsilon)) context.lineTo(x10, y10); + + // Does the sector’s inner ring (or point) have rounded corners? + else if (rc0 > epsilon) { + t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw); + t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw); + + context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01); + + // Have the corners merged? + if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t1.y01, t1.x01), !cw); + + // Otherwise, draw the two corners and the ring. + else { + context.arc(t0.cx, t0.cy, rc0, atan2(t0.y01, t0.x01), atan2(t0.y11, t0.x11), !cw); + context.arc(0, 0, r0, atan2(t0.cy + t0.y11, t0.cx + t0.x11), atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw); + context.arc(t1.cx, t1.cy, rc0, atan2(t1.y11, t1.x11), atan2(t1.y01, t1.x01), !cw); + } + } + + // Or is the inner ring just a circular arc? + else context.arc(0, 0, r0, a10, a00, cw); + } + + context.closePath(); + + if (buffer) return context = null, buffer + "" || null; + } + + arc.centroid = function() { + var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, + a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi / 2; + return [cos(a) * r, sin(a) * r]; + }; + + arc.innerRadius = function(_) { + return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant(+_), arc) : innerRadius; + }; + + arc.outerRadius = function(_) { + return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant(+_), arc) : outerRadius; + }; + + arc.cornerRadius = function(_) { + return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant(+_), arc) : cornerRadius; + }; + + arc.padRadius = function(_) { + return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant(+_), arc) : padRadius; + }; + + arc.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), arc) : startAngle; + }; + + arc.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), arc) : endAngle; + }; + + arc.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), arc) : padAngle; + }; + + arc.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), arc) : context; + }; + + return arc; +}; + +function Linear(context) { + this._context = context; +} + +Linear.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: this._context.lineTo(x, y); break; + } + } +}; + +var curveLinear = function(context) { + return new Linear(context); +}; + +function x(p) { + return p[0]; +} + +function y(p) { + return p[1]; +} + +var line = function() { + var x$$1 = x, + y$$1 = y, + defined = constant(true), + context = null, + curve = curveLinear, + output = null; + + function line(data) { + var i, + n = data.length, + d, + defined0 = false, + buffer; + + if (context == null) output = curve(buffer = d3Path.path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) output.lineStart(); + else output.lineEnd(); + } + if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data)); + } + + if (buffer) return output = null, buffer + "" || null; + } + + line.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), line) : x$$1; + }; + + line.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), line) : y$$1; + }; + + line.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), line) : defined; + }; + + line.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve; + }; + + line.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context; + }; + + return line; +}; + +var area = function() { + var x0 = x, + x1 = null, + y0 = constant(0), + y1 = y, + defined = constant(true), + context = null, + curve = curveLinear, + output = null; + + function area(data) { + var i, + j, + k, + n = data.length, + d, + defined0 = false, + buffer, + x0z = new Array(n), + y0z = new Array(n); + + if (context == null) output = curve(buffer = d3Path.path()); + + for (i = 0; i <= n; ++i) { + if (!(i < n && defined(d = data[i], i, data)) === defined0) { + if (defined0 = !defined0) { + j = i; + output.areaStart(); + output.lineStart(); + } else { + output.lineEnd(); + output.lineStart(); + for (k = i - 1; k >= j; --k) { + output.point(x0z[k], y0z[k]); + } + output.lineEnd(); + output.areaEnd(); + } + } + if (defined0) { + x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data); + output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]); + } + } + + if (buffer) return output = null, buffer + "" || null; + } + + function arealine() { + return line().defined(defined).curve(curve).context(context); + } + + area.x = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), x1 = null, area) : x0; + }; + + area.x0 = function(_) { + return arguments.length ? (x0 = typeof _ === "function" ? _ : constant(+_), area) : x0; + }; + + area.x1 = function(_) { + return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : x1; + }; + + area.y = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), y1 = null, area) : y0; + }; + + area.y0 = function(_) { + return arguments.length ? (y0 = typeof _ === "function" ? _ : constant(+_), area) : y0; + }; + + area.y1 = function(_) { + return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant(+_), area) : y1; + }; + + area.lineX0 = + area.lineY0 = function() { + return arealine().x(x0).y(y0); + }; + + area.lineY1 = function() { + return arealine().x(x0).y(y1); + }; + + area.lineX1 = function() { + return arealine().x(x1).y(y0); + }; + + area.defined = function(_) { + return arguments.length ? (defined = typeof _ === "function" ? _ : constant(!!_), area) : defined; + }; + + area.curve = function(_) { + return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve; + }; + + area.context = function(_) { + return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context; + }; + + return area; +}; + +var descending = function(a, b) { + return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN; +}; + +var identity = function(d) { + return d; +}; + +var pie = function() { + var value = identity, + sortValues = descending, + sort = null, + startAngle = constant(0), + endAngle = constant(tau), + padAngle = constant(0); + + function pie(data) { + var i, + n = data.length, + j, + k, + sum = 0, + index = new Array(n), + arcs = new Array(n), + a0 = +startAngle.apply(this, arguments), + da = Math.min(tau, Math.max(-tau, endAngle.apply(this, arguments) - a0)), + a1, + p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)), + pa = p * (da < 0 ? -1 : 1), + v; + + for (i = 0; i < n; ++i) { + if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) { + sum += v; + } + } + + // Optionally sort the arcs by previously-computed values or by data. + if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); }); + else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); }); + + // Compute the arcs! They are stored in the original data's order. + for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) { + j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = { + data: data[j], + index: i, + value: v, + startAngle: a0, + endAngle: a1, + padAngle: p + }; + } + + return arcs; + } + + pie.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), pie) : value; + }; + + pie.sortValues = function(_) { + return arguments.length ? (sortValues = _, sort = null, pie) : sortValues; + }; + + pie.sort = function(_) { + return arguments.length ? (sort = _, sortValues = null, pie) : sort; + }; + + pie.startAngle = function(_) { + return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant(+_), pie) : startAngle; + }; + + pie.endAngle = function(_) { + return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant(+_), pie) : endAngle; + }; + + pie.padAngle = function(_) { + return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant(+_), pie) : padAngle; + }; + + return pie; +}; + +var curveRadialLinear = curveRadial(curveLinear); + +function Radial(curve) { + this._curve = curve; +} + +Radial.prototype = { + areaStart: function() { + this._curve.areaStart(); + }, + areaEnd: function() { + this._curve.areaEnd(); + }, + lineStart: function() { + this._curve.lineStart(); + }, + lineEnd: function() { + this._curve.lineEnd(); + }, + point: function(a, r) { + this._curve.point(r * Math.sin(a), r * -Math.cos(a)); + } +}; + +function curveRadial(curve) { + + function radial(context) { + return new Radial(curve(context)); + } + + radial._curve = curve; + + return radial; +} + +function lineRadial(l) { + var c = l.curve; + + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + + l.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return l; +} + +var lineRadial$1 = function() { + return lineRadial(line().curve(curveRadialLinear)); +}; + +var areaRadial = function() { + var a = area().curve(curveRadialLinear), + c = a.curve, + x0 = a.lineX0, + x1 = a.lineX1, + y0 = a.lineY0, + y1 = a.lineY1; + + a.angle = a.x, delete a.x; + a.startAngle = a.x0, delete a.x0; + a.endAngle = a.x1, delete a.x1; + a.radius = a.y, delete a.y; + a.innerRadius = a.y0, delete a.y0; + a.outerRadius = a.y1, delete a.y1; + a.lineStartAngle = function() { return lineRadial(x0()); }, delete a.lineX0; + a.lineEndAngle = function() { return lineRadial(x1()); }, delete a.lineX1; + a.lineInnerRadius = function() { return lineRadial(y0()); }, delete a.lineY0; + a.lineOuterRadius = function() { return lineRadial(y1()); }, delete a.lineY1; + + a.curve = function(_) { + return arguments.length ? c(curveRadial(_)) : c()._curve; + }; + + return a; +}; + +var pointRadial = function(x, y) { + return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)]; +}; + +var slice = Array.prototype.slice; + +function linkSource(d) { + return d.source; +} + +function linkTarget(d) { + return d.target; +} + +function link(curve) { + var source = linkSource, + target = linkTarget, + x$$1 = x, + y$$1 = y, + context = null; + + function link() { + var buffer, argv = slice.call(arguments), s = source.apply(this, argv), t = target.apply(this, argv); + if (!context) context = buffer = d3Path.path(); + curve(context, +x$$1.apply(this, (argv[0] = s, argv)), +y$$1.apply(this, argv), +x$$1.apply(this, (argv[0] = t, argv)), +y$$1.apply(this, argv)); + if (buffer) return context = null, buffer + "" || null; + } + + link.source = function(_) { + return arguments.length ? (source = _, link) : source; + }; + + link.target = function(_) { + return arguments.length ? (target = _, link) : target; + }; + + link.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), link) : x$$1; + }; + + link.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), link) : y$$1; + }; + + link.context = function(_) { + return arguments.length ? ((context = _ == null ? null : _), link) : context; + }; + + return link; +} + +function curveHorizontal(context, x0, y0, x1, y1) { + context.moveTo(x0, y0); + context.bezierCurveTo(x0 = (x0 + x1) / 2, y0, x0, y1, x1, y1); +} + +function curveVertical(context, x0, y0, x1, y1) { + context.moveTo(x0, y0); + context.bezierCurveTo(x0, y0 = (y0 + y1) / 2, x1, y0, x1, y1); +} + +function curveRadial$1(context, x0, y0, x1, y1) { + var p0 = pointRadial(x0, y0), + p1 = pointRadial(x0, y0 = (y0 + y1) / 2), + p2 = pointRadial(x1, y0), + p3 = pointRadial(x1, y1); + context.moveTo(p0[0], p0[1]); + context.bezierCurveTo(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1]); +} + +function linkHorizontal() { + return link(curveHorizontal); +} + +function linkVertical() { + return link(curveVertical); +} + +function linkRadial() { + var l = link(curveRadial$1); + l.angle = l.x, delete l.x; + l.radius = l.y, delete l.y; + return l; +} + +var circle = { + draw: function(context, size) { + var r = Math.sqrt(size / pi); + context.moveTo(r, 0); + context.arc(0, 0, r, 0, tau); + } +}; + +var cross = { + draw: function(context, size) { + var r = Math.sqrt(size / 5) / 2; + context.moveTo(-3 * r, -r); + context.lineTo(-r, -r); + context.lineTo(-r, -3 * r); + context.lineTo(r, -3 * r); + context.lineTo(r, -r); + context.lineTo(3 * r, -r); + context.lineTo(3 * r, r); + context.lineTo(r, r); + context.lineTo(r, 3 * r); + context.lineTo(-r, 3 * r); + context.lineTo(-r, r); + context.lineTo(-3 * r, r); + context.closePath(); + } +}; + +var tan30 = Math.sqrt(1 / 3); +var tan30_2 = tan30 * 2; + +var diamond = { + draw: function(context, size) { + var y = Math.sqrt(size / tan30_2), + x = y * tan30; + context.moveTo(0, -y); + context.lineTo(x, 0); + context.lineTo(0, y); + context.lineTo(-x, 0); + context.closePath(); + } +}; + +var ka = 0.89081309152928522810; +var kr = Math.sin(pi / 10) / Math.sin(7 * pi / 10); +var kx = Math.sin(tau / 10) * kr; +var ky = -Math.cos(tau / 10) * kr; + +var star = { + draw: function(context, size) { + var r = Math.sqrt(size * ka), + x = kx * r, + y = ky * r; + context.moveTo(0, -r); + context.lineTo(x, y); + for (var i = 1; i < 5; ++i) { + var a = tau * i / 5, + c = Math.cos(a), + s = Math.sin(a); + context.lineTo(s * r, -c * r); + context.lineTo(c * x - s * y, s * x + c * y); + } + context.closePath(); + } +}; + +var square = { + draw: function(context, size) { + var w = Math.sqrt(size), + x = -w / 2; + context.rect(x, x, w, w); + } +}; + +var sqrt3 = Math.sqrt(3); + +var triangle = { + draw: function(context, size) { + var y = -Math.sqrt(size / (sqrt3 * 3)); + context.moveTo(0, y * 2); + context.lineTo(-sqrt3 * y, -y); + context.lineTo(sqrt3 * y, -y); + context.closePath(); + } +}; + +var c = -0.5; +var s = Math.sqrt(3) / 2; +var k = 1 / Math.sqrt(12); +var a = (k / 2 + 1) * 3; + +var wye = { + draw: function(context, size) { + var r = Math.sqrt(size / a), + x0 = r / 2, + y0 = r * k, + x1 = x0, + y1 = r * k + r, + x2 = -x1, + y2 = y1; + context.moveTo(x0, y0); + context.lineTo(x1, y1); + context.lineTo(x2, y2); + context.lineTo(c * x0 - s * y0, s * x0 + c * y0); + context.lineTo(c * x1 - s * y1, s * x1 + c * y1); + context.lineTo(c * x2 - s * y2, s * x2 + c * y2); + context.lineTo(c * x0 + s * y0, c * y0 - s * x0); + context.lineTo(c * x1 + s * y1, c * y1 - s * x1); + context.lineTo(c * x2 + s * y2, c * y2 - s * x2); + context.closePath(); + } +}; + +var symbols = [ + circle, + cross, + diamond, + square, + star, + triangle, + wye +]; + +var symbol = function() { + var type = constant(circle), + size = constant(64), + context = null; + + function symbol() { + var buffer; + if (!context) context = buffer = d3Path.path(); + type.apply(this, arguments).draw(context, +size.apply(this, arguments)); + if (buffer) return context = null, buffer + "" || null; + } + + symbol.type = function(_) { + return arguments.length ? (type = typeof _ === "function" ? _ : constant(_), symbol) : type; + }; + + symbol.size = function(_) { + return arguments.length ? (size = typeof _ === "function" ? _ : constant(+_), symbol) : size; + }; + + symbol.context = function(_) { + return arguments.length ? (context = _ == null ? null : _, symbol) : context; + }; + + return symbol; +}; + +var noop = function() {}; + +function point(that, x, y) { + that._context.bezierCurveTo( + (2 * that._x0 + that._x1) / 3, + (2 * that._y0 + that._y1) / 3, + (that._x0 + 2 * that._x1) / 3, + (that._y0 + 2 * that._y1) / 3, + (that._x0 + 4 * that._x1 + x) / 6, + (that._y0 + 4 * that._y1 + y) / 6 + ); +} + +function Basis(context) { + this._context = context; +} + +Basis.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 3: point(this, this._x1, this._y1); // proceed + case 2: this._context.lineTo(this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basis = function(context) { + return new Basis(context); +}; + +function BasisClosed(context) { + this._context = context; +} + +BasisClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x2, this._y2); + this._context.closePath(); + break; + } + case 2: { + this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3); + this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x2, this._y2); + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x2 = x, this._y2 = y; break; + case 1: this._point = 2; this._x3 = x, this._y3 = y; break; + case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break; + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basisClosed = function(context) { + return new BasisClosed(context); +}; + +function BasisOpen(context) { + this._context = context; +} + +BasisOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break; + case 3: this._point = 4; // proceed + default: point(this, x, y); break; + } + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + } +}; + +var basisOpen = function(context) { + return new BasisOpen(context); +}; + +function Bundle(context, beta) { + this._basis = new Basis(context); + this._beta = beta; +} + +Bundle.prototype = { + lineStart: function() { + this._x = []; + this._y = []; + this._basis.lineStart(); + }, + lineEnd: function() { + var x = this._x, + y = this._y, + j = x.length - 1; + + if (j > 0) { + var x0 = x[0], + y0 = y[0], + dx = x[j] - x0, + dy = y[j] - y0, + i = -1, + t; + + while (++i <= j) { + t = i / j; + this._basis.point( + this._beta * x[i] + (1 - this._beta) * (x0 + t * dx), + this._beta * y[i] + (1 - this._beta) * (y0 + t * dy) + ); + } + } + + this._x = this._y = null; + this._basis.lineEnd(); + }, + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } +}; + +var bundle = ((function custom(beta) { + + function bundle(context) { + return beta === 1 ? new Basis(context) : new Bundle(context, beta); + } + + bundle.beta = function(beta) { + return custom(+beta); + }; + + return bundle; +}))(0.85); + +function point$1(that, x, y) { + that._context.bezierCurveTo( + that._x1 + that._k * (that._x2 - that._x0), + that._y1 + that._k * (that._y2 - that._y0), + that._x2 + that._k * (that._x1 - x), + that._y2 + that._k * (that._y1 - y), + that._x2, + that._y2 + ); +} + +function Cardinal(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +Cardinal.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: point$1(this, this._x1, this._y1); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; this._x1 = x, this._y1 = y; break; + case 2: this._point = 3; // proceed + default: point$1(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinal = ((function custom(tension) { + + function cardinal(context) { + return new Cardinal(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +}))(0); + +function CardinalClosed(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$1(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinalClosed = ((function custom(tension) { + + function cardinal(context) { + return new CardinalClosed(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +}))(0); + +function CardinalOpen(context, tension) { + this._context = context; + this._k = (1 - tension) / 6; +} + +CardinalOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$1(this, x, y); break; + } + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var cardinalOpen = ((function custom(tension) { + + function cardinal(context) { + return new CardinalOpen(context, tension); + } + + cardinal.tension = function(tension) { + return custom(+tension); + }; + + return cardinal; +}))(0); + +function point$2(that, x, y) { + var x1 = that._x1, + y1 = that._y1, + x2 = that._x2, + y2 = that._y2; + + if (that._l01_a > epsilon) { + var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, + n = 3 * that._l01_a * (that._l01_a + that._l12_a); + x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n; + y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n; + } + + if (that._l23_a > epsilon) { + var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, + m = 3 * that._l23_a * (that._l23_a + that._l12_a); + x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m; + y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m; + } + + that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2); +} + +function CatmullRom(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRom.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x2, this._y2); break; + case 3: this.point(this._x2, this._y2); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; // proceed + default: point$2(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRom = ((function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +}))(0.5); + +function CatmullRomClosed(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRomClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = + this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 1: { + this._context.moveTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 2: { + this._context.lineTo(this._x3, this._y3); + this._context.closePath(); + break; + } + case 3: { + this.point(this._x3, this._y3); + this.point(this._x4, this._y4); + this.point(this._x5, this._y5); + break; + } + } + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; this._x3 = x, this._y3 = y; break; + case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break; + case 2: this._point = 3; this._x5 = x, this._y5 = y; break; + default: point$2(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRomClosed = ((function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +}))(0.5); + +function CatmullRomOpen(context, alpha) { + this._context = context; + this._alpha = alpha; +} + +CatmullRomOpen.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = this._x2 = + this._y0 = this._y1 = this._y2 = NaN; + this._l01_a = this._l12_a = this._l23_a = + this._l01_2a = this._l12_2a = this._l23_2a = + this._point = 0; + }, + lineEnd: function() { + if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + + if (this._point) { + var x23 = this._x2 - x, + y23 = this._y2 - y; + this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha)); + } + + switch (this._point) { + case 0: this._point = 1; break; + case 1: this._point = 2; break; + case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break; + case 3: this._point = 4; // proceed + default: point$2(this, x, y); break; + } + + this._l01_a = this._l12_a, this._l12_a = this._l23_a; + this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a; + this._x0 = this._x1, this._x1 = this._x2, this._x2 = x; + this._y0 = this._y1, this._y1 = this._y2, this._y2 = y; + } +}; + +var catmullRomOpen = ((function custom(alpha) { + + function catmullRom(context) { + return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0); + } + + catmullRom.alpha = function(alpha) { + return custom(+alpha); + }; + + return catmullRom; +}))(0.5); + +function LinearClosed(context) { + this._context = context; +} + +LinearClosed.prototype = { + areaStart: noop, + areaEnd: noop, + lineStart: function() { + this._point = 0; + }, + lineEnd: function() { + if (this._point) this._context.closePath(); + }, + point: function(x, y) { + x = +x, y = +y; + if (this._point) this._context.lineTo(x, y); + else this._point = 1, this._context.moveTo(x, y); + } +}; + +var linearClosed = function(context) { + return new LinearClosed(context); +}; + +function sign(x) { + return x < 0 ? -1 : 1; +} + +// Calculate the slopes of the tangents (Hermite-type interpolation) based on +// the following paper: Steffen, M. 1990. A Simple Method for Monotonic +// Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO. +// NOV(II), P. 443, 1990. +function slope3(that, x2, y2) { + var h0 = that._x1 - that._x0, + h1 = x2 - that._x1, + s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), + s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0), + p = (s0 * h1 + s1 * h0) / (h0 + h1); + return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0; +} + +// Calculate a one-sided slope. +function slope2(that, t) { + var h = that._x1 - that._x0; + return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t; +} + +// According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations +// "you can express cubic Hermite interpolation in terms of cubic Bézier curves +// with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1". +function point$3(that, t0, t1) { + var x0 = that._x0, + y0 = that._y0, + x1 = that._x1, + y1 = that._y1, + dx = (x1 - x0) / 3; + that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1); +} + +function MonotoneX(context) { + this._context = context; +} + +MonotoneX.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x0 = this._x1 = + this._y0 = this._y1 = + this._t0 = NaN; + this._point = 0; + }, + lineEnd: function() { + switch (this._point) { + case 2: this._context.lineTo(this._x1, this._y1); break; + case 3: point$3(this, this._t0, slope2(this, this._t0)); break; + } + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + this._line = 1 - this._line; + }, + point: function(x, y) { + var t1 = NaN; + + x = +x, y = +y; + if (x === this._x1 && y === this._y1) return; // Ignore coincident points. + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; break; + case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break; + default: point$3(this, this._t0, t1 = slope3(this, x, y)); break; + } + + this._x0 = this._x1, this._x1 = x; + this._y0 = this._y1, this._y1 = y; + this._t0 = t1; + } +}; + +function MonotoneY(context) { + this._context = new ReflectContext(context); +} + +(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) { + MonotoneX.prototype.point.call(this, y, x); +}; + +function ReflectContext(context) { + this._context = context; +} + +ReflectContext.prototype = { + moveTo: function(x, y) { this._context.moveTo(y, x); }, + closePath: function() { this._context.closePath(); }, + lineTo: function(x, y) { this._context.lineTo(y, x); }, + bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); } +}; + +function monotoneX(context) { + return new MonotoneX(context); +} + +function monotoneY(context) { + return new MonotoneY(context); +} + +function Natural(context) { + this._context = context; +} + +Natural.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x = []; + this._y = []; + }, + lineEnd: function() { + var x = this._x, + y = this._y, + n = x.length; + + if (n) { + this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]); + if (n === 2) { + this._context.lineTo(x[1], y[1]); + } else { + var px = controlPoints(x), + py = controlPoints(y); + for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) { + this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]); + } + } + } + + if (this._line || (this._line !== 0 && n === 1)) this._context.closePath(); + this._line = 1 - this._line; + this._x = this._y = null; + }, + point: function(x, y) { + this._x.push(+x); + this._y.push(+y); + } +}; + +// See https://www.particleincell.com/2012/bezier-splines/ for derivation. +function controlPoints(x) { + var i, + n = x.length - 1, + m, + a = new Array(n), + b = new Array(n), + r = new Array(n); + a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1]; + for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1]; + a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n]; + for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1]; + a[n - 1] = r[n - 1] / b[n - 1]; + for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i]; + b[n - 1] = (x[n] + a[n - 1]) / 2; + for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1]; + return [a, b]; +} + +var natural = function(context) { + return new Natural(context); +}; + +function Step(context, t) { + this._context = context; + this._t = t; +} + +Step.prototype = { + areaStart: function() { + this._line = 0; + }, + areaEnd: function() { + this._line = NaN; + }, + lineStart: function() { + this._x = this._y = NaN; + this._point = 0; + }, + lineEnd: function() { + if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y); + if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath(); + if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line; + }, + point: function(x, y) { + x = +x, y = +y; + switch (this._point) { + case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break; + case 1: this._point = 2; // proceed + default: { + if (this._t <= 0) { + this._context.lineTo(this._x, y); + this._context.lineTo(x, y); + } else { + var x1 = this._x * (1 - this._t) + x * this._t; + this._context.lineTo(x1, this._y); + this._context.lineTo(x1, y); + } + break; + } + } + this._x = x, this._y = y; + } +}; + +var step = function(context) { + return new Step(context, 0.5); +}; + +function stepBefore(context) { + return new Step(context, 0); +} + +function stepAfter(context) { + return new Step(context, 1); +} + +var none = function(series, order) { + if (!((n = series.length) > 1)) return; + for (var i = 1, j, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) { + s0 = s1, s1 = series[order[i]]; + for (j = 0; j < m; ++j) { + s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1]; + } + } +}; + +var none$1 = function(series) { + var n = series.length, o = new Array(n); + while (--n >= 0) o[n] = n; + return o; +}; + +function stackValue(d, key) { + return d[key]; +} + +var stack = function() { + var keys = constant([]), + order = none$1, + offset = none, + value = stackValue; + + function stack(data) { + var kz = keys.apply(this, arguments), + i, + m = data.length, + n = kz.length, + sz = new Array(n), + oz; + + for (i = 0; i < n; ++i) { + for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) { + si[j] = sij = [0, +value(data[j], ki, j, data)]; + sij.data = data[j]; + } + si.key = ki; + } + + for (i = 0, oz = order(sz); i < n; ++i) { + sz[oz[i]].index = i; + } + + offset(sz, oz); + return sz; + } + + stack.keys = function(_) { + return arguments.length ? (keys = typeof _ === "function" ? _ : constant(slice.call(_)), stack) : keys; + }; + + stack.value = function(_) { + return arguments.length ? (value = typeof _ === "function" ? _ : constant(+_), stack) : value; + }; + + stack.order = function(_) { + return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant(slice.call(_)), stack) : order; + }; + + stack.offset = function(_) { + return arguments.length ? (offset = _ == null ? none : _, stack) : offset; + }; + + return stack; +}; + +var expand = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) { + for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0; + if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y; + } + none(series, order); +}; + +var diverging = function(series, order) { + if (!((n = series.length) > 1)) return; + for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) { + for (yp = yn = 0, i = 0; i < n; ++i) { + if ((dy = (d = series[order[i]][j])[1] - d[0]) >= 0) { + d[0] = yp, d[1] = yp += dy; + } else if (dy < 0) { + d[1] = yn, d[0] = yn += dy; + } else { + d[0] = yp; + } + } + } +}; + +var silhouette = function(series, order) { + if (!((n = series.length) > 0)) return; + for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) { + for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0; + s0[j][1] += s0[j][0] = -y / 2; + } + none(series, order); +}; + +var wiggle = function(series, order) { + if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return; + for (var y = 0, j = 1, s0, m, n; j < m; ++j) { + for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) { + var si = series[order[i]], + sij0 = si[j][1] || 0, + sij1 = si[j - 1][1] || 0, + s3 = (sij0 - sij1) / 2; + for (var k = 0; k < i; ++k) { + var sk = series[order[k]], + skj0 = sk[j][1] || 0, + skj1 = sk[j - 1][1] || 0; + s3 += skj0 - skj1; + } + s1 += sij0, s2 += s3 * sij0; + } + s0[j - 1][1] += s0[j - 1][0] = y; + if (s1) y -= s2 / s1; + } + s0[j - 1][1] += s0[j - 1][0] = y; + none(series, order); +}; + +var ascending = function(series) { + var sums = series.map(sum); + return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; }); +}; + +function sum(series) { + var s = 0, i = -1, n = series.length, v; + while (++i < n) if (v = +series[i][1]) s += v; + return s; +} + +var descending$1 = function(series) { + return ascending(series).reverse(); +}; + +var insideOut = function(series) { + var n = series.length, + i, + j, + sums = series.map(sum), + order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }), + top = 0, + bottom = 0, + tops = [], + bottoms = []; + + for (i = 0; i < n; ++i) { + j = order[i]; + if (top < bottom) { + top += sums[j]; + tops.push(j); + } else { + bottom += sums[j]; + bottoms.push(j); + } + } + + return bottoms.reverse().concat(tops); +}; + +var reverse = function(series) { + return none$1(series).reverse(); +}; + +exports.arc = arc; +exports.area = area; +exports.line = line; +exports.pie = pie; +exports.areaRadial = areaRadial; +exports.radialArea = areaRadial; +exports.lineRadial = lineRadial$1; +exports.radialLine = lineRadial$1; +exports.pointRadial = pointRadial; +exports.linkHorizontal = linkHorizontal; +exports.linkVertical = linkVertical; +exports.linkRadial = linkRadial; +exports.symbol = symbol; +exports.symbols = symbols; +exports.symbolCircle = circle; +exports.symbolCross = cross; +exports.symbolDiamond = diamond; +exports.symbolSquare = square; +exports.symbolStar = star; +exports.symbolTriangle = triangle; +exports.symbolWye = wye; +exports.curveBasisClosed = basisClosed; +exports.curveBasisOpen = basisOpen; +exports.curveBasis = basis; +exports.curveBundle = bundle; +exports.curveCardinalClosed = cardinalClosed; +exports.curveCardinalOpen = cardinalOpen; +exports.curveCardinal = cardinal; +exports.curveCatmullRomClosed = catmullRomClosed; +exports.curveCatmullRomOpen = catmullRomOpen; +exports.curveCatmullRom = catmullRom; +exports.curveLinearClosed = linearClosed; +exports.curveLinear = curveLinear; +exports.curveMonotoneX = monotoneX; +exports.curveMonotoneY = monotoneY; +exports.curveNatural = natural; +exports.curveStep = step; +exports.curveStepAfter = stepAfter; +exports.curveStepBefore = stepBefore; +exports.stack = stack; +exports.stackOffsetExpand = expand; +exports.stackOffsetDiverging = diverging; +exports.stackOffsetNone = none; +exports.stackOffsetSilhouette = silhouette; +exports.stackOffsetWiggle = wiggle; +exports.stackOrderAscending = ascending; +exports.stackOrderDescending = descending$1; +exports.stackOrderInsideOut = insideOut; +exports.stackOrderNone = none$1; +exports.stackOrderReverse = reverse; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-path":38}],47:[function(require,module,exports){ +// https://d3js.org/d3-time-format/ Version 2.1.1. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-time')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-time'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3)); +}(this, (function (exports,d3Time) { 'use strict'; + +function localDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); + date.setFullYear(d.y); + return date; + } + return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); +} + +function utcDate(d) { + if (0 <= d.y && d.y < 100) { + var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); + date.setUTCFullYear(d.y); + return date; + } + return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); +} + +function newYear(y) { + return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; +} + +function formatLocale(locale) { + var locale_dateTime = locale.dateTime, + locale_date = locale.date, + locale_time = locale.time, + locale_periods = locale.periods, + locale_weekdays = locale.days, + locale_shortWeekdays = locale.shortDays, + locale_months = locale.months, + locale_shortMonths = locale.shortMonths; + + var periodRe = formatRe(locale_periods), + periodLookup = formatLookup(locale_periods), + weekdayRe = formatRe(locale_weekdays), + weekdayLookup = formatLookup(locale_weekdays), + shortWeekdayRe = formatRe(locale_shortWeekdays), + shortWeekdayLookup = formatLookup(locale_shortWeekdays), + monthRe = formatRe(locale_months), + monthLookup = formatLookup(locale_months), + shortMonthRe = formatRe(locale_shortMonths), + shortMonthLookup = formatLookup(locale_shortMonths); + + var formats = { + "a": formatShortWeekday, + "A": formatWeekday, + "b": formatShortMonth, + "B": formatMonth, + "c": null, + "d": formatDayOfMonth, + "e": formatDayOfMonth, + "f": formatMicroseconds, + "H": formatHour24, + "I": formatHour12, + "j": formatDayOfYear, + "L": formatMilliseconds, + "m": formatMonthNumber, + "M": formatMinutes, + "p": formatPeriod, + "Q": formatUnixTimestamp, + "s": formatUnixTimestampSeconds, + "S": formatSeconds, + "u": formatWeekdayNumberMonday, + "U": formatWeekNumberSunday, + "V": formatWeekNumberISO, + "w": formatWeekdayNumberSunday, + "W": formatWeekNumberMonday, + "x": null, + "X": null, + "y": formatYear, + "Y": formatFullYear, + "Z": formatZone, + "%": formatLiteralPercent + }; + + var utcFormats = { + "a": formatUTCShortWeekday, + "A": formatUTCWeekday, + "b": formatUTCShortMonth, + "B": formatUTCMonth, + "c": null, + "d": formatUTCDayOfMonth, + "e": formatUTCDayOfMonth, + "f": formatUTCMicroseconds, + "H": formatUTCHour24, + "I": formatUTCHour12, + "j": formatUTCDayOfYear, + "L": formatUTCMilliseconds, + "m": formatUTCMonthNumber, + "M": formatUTCMinutes, + "p": formatUTCPeriod, + "Q": formatUnixTimestamp, + "s": formatUnixTimestampSeconds, + "S": formatUTCSeconds, + "u": formatUTCWeekdayNumberMonday, + "U": formatUTCWeekNumberSunday, + "V": formatUTCWeekNumberISO, + "w": formatUTCWeekdayNumberSunday, + "W": formatUTCWeekNumberMonday, + "x": null, + "X": null, + "y": formatUTCYear, + "Y": formatUTCFullYear, + "Z": formatUTCZone, + "%": formatLiteralPercent + }; + + var parses = { + "a": parseShortWeekday, + "A": parseWeekday, + "b": parseShortMonth, + "B": parseMonth, + "c": parseLocaleDateTime, + "d": parseDayOfMonth, + "e": parseDayOfMonth, + "f": parseMicroseconds, + "H": parseHour24, + "I": parseHour24, + "j": parseDayOfYear, + "L": parseMilliseconds, + "m": parseMonthNumber, + "M": parseMinutes, + "p": parsePeriod, + "Q": parseUnixTimestamp, + "s": parseUnixTimestampSeconds, + "S": parseSeconds, + "u": parseWeekdayNumberMonday, + "U": parseWeekNumberSunday, + "V": parseWeekNumberISO, + "w": parseWeekdayNumberSunday, + "W": parseWeekNumberMonday, + "x": parseLocaleDate, + "X": parseLocaleTime, + "y": parseYear, + "Y": parseFullYear, + "Z": parseZone, + "%": parseLiteralPercent + }; + + // These recursive directive definitions must be deferred. + formats.x = newFormat(locale_date, formats); + formats.X = newFormat(locale_time, formats); + formats.c = newFormat(locale_dateTime, formats); + utcFormats.x = newFormat(locale_date, utcFormats); + utcFormats.X = newFormat(locale_time, utcFormats); + utcFormats.c = newFormat(locale_dateTime, utcFormats); + + function newFormat(specifier, formats) { + return function(date) { + var string = [], + i = -1, + j = 0, + n = specifier.length, + c, + pad, + format; + + if (!(date instanceof Date)) date = new Date(+date); + + while (++i < n) { + if (specifier.charCodeAt(i) === 37) { + string.push(specifier.slice(j, i)); + if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); + else pad = c === "e" ? " " : "0"; + if (format = formats[c]) c = format(date, pad); + string.push(c); + j = i + 1; + } + } + + string.push(specifier.slice(j, i)); + return string.join(""); + }; + } + + function newParse(specifier, newDate) { + return function(string) { + var d = newYear(1900), + i = parseSpecifier(d, specifier, string += "", 0), + week, day; + if (i != string.length) return null; + + // If a UNIX timestamp is specified, return it. + if ("Q" in d) return new Date(d.Q); + + // The am-pm flag is 0 for AM, and 1 for PM. + if ("p" in d) d.H = d.H % 12 + d.p * 12; + + // Convert day-of-week and week-of-year to day-of-year. + if ("V" in d) { + if (d.V < 1 || d.V > 53) return null; + if (!("w" in d)) d.w = 1; + if ("Z" in d) { + week = utcDate(newYear(d.y)), day = week.getUTCDay(); + week = day > 4 || day === 0 ? d3Time.utcMonday.ceil(week) : d3Time.utcMonday(week); + week = d3Time.utcDay.offset(week, (d.V - 1) * 7); + d.y = week.getUTCFullYear(); + d.m = week.getUTCMonth(); + d.d = week.getUTCDate() + (d.w + 6) % 7; + } else { + week = newDate(newYear(d.y)), day = week.getDay(); + week = day > 4 || day === 0 ? d3Time.timeMonday.ceil(week) : d3Time.timeMonday(week); + week = d3Time.timeDay.offset(week, (d.V - 1) * 7); + d.y = week.getFullYear(); + d.m = week.getMonth(); + d.d = week.getDate() + (d.w + 6) % 7; + } + } else if ("W" in d || "U" in d) { + if (!("w" in d)) d.w = "u" in d ? d.u % 7 : "W" in d ? 1 : 0; + day = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay(); + d.m = 0; + d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7; + } + + // If a time zone is specified, all fields are interpreted as UTC and then + // offset according to the specified time zone. + if ("Z" in d) { + d.H += d.Z / 100 | 0; + d.M += d.Z % 100; + return utcDate(d); + } + + // Otherwise, all fields are in local time. + return newDate(d); + }; + } + + function parseSpecifier(d, specifier, string, j) { + var i = 0, + n = specifier.length, + m = string.length, + c, + parse; + + while (i < n) { + if (j >= m) return -1; + c = specifier.charCodeAt(i++); + if (c === 37) { + c = specifier.charAt(i++); + parse = parses[c in pads ? specifier.charAt(i++) : c]; + if (!parse || ((j = parse(d, string, j)) < 0)) return -1; + } else if (c != string.charCodeAt(j++)) { + return -1; + } + } + + return j; + } + + function parsePeriod(d, string, i) { + var n = periodRe.exec(string.slice(i)); + return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortWeekday(d, string, i) { + var n = shortWeekdayRe.exec(string.slice(i)); + return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseWeekday(d, string, i) { + var n = weekdayRe.exec(string.slice(i)); + return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseShortMonth(d, string, i) { + var n = shortMonthRe.exec(string.slice(i)); + return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseMonth(d, string, i) { + var n = monthRe.exec(string.slice(i)); + return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1; + } + + function parseLocaleDateTime(d, string, i) { + return parseSpecifier(d, locale_dateTime, string, i); + } + + function parseLocaleDate(d, string, i) { + return parseSpecifier(d, locale_date, string, i); + } + + function parseLocaleTime(d, string, i) { + return parseSpecifier(d, locale_time, string, i); + } + + function formatShortWeekday(d) { + return locale_shortWeekdays[d.getDay()]; + } + + function formatWeekday(d) { + return locale_weekdays[d.getDay()]; + } + + function formatShortMonth(d) { + return locale_shortMonths[d.getMonth()]; + } + + function formatMonth(d) { + return locale_months[d.getMonth()]; + } + + function formatPeriod(d) { + return locale_periods[+(d.getHours() >= 12)]; + } + + function formatUTCShortWeekday(d) { + return locale_shortWeekdays[d.getUTCDay()]; + } + + function formatUTCWeekday(d) { + return locale_weekdays[d.getUTCDay()]; + } + + function formatUTCShortMonth(d) { + return locale_shortMonths[d.getUTCMonth()]; + } + + function formatUTCMonth(d) { + return locale_months[d.getUTCMonth()]; + } + + function formatUTCPeriod(d) { + return locale_periods[+(d.getUTCHours() >= 12)]; + } + + return { + format: function(specifier) { + var f = newFormat(specifier += "", formats); + f.toString = function() { return specifier; }; + return f; + }, + parse: function(specifier) { + var p = newParse(specifier += "", localDate); + p.toString = function() { return specifier; }; + return p; + }, + utcFormat: function(specifier) { + var f = newFormat(specifier += "", utcFormats); + f.toString = function() { return specifier; }; + return f; + }, + utcParse: function(specifier) { + var p = newParse(specifier, utcDate); + p.toString = function() { return specifier; }; + return p; + } + }; +} + +var pads = {"-": "", "_": " ", "0": "0"}; +var numberRe = /^\s*\d+/; +var percentRe = /^%/; +var requoteRe = /[\\^$*+?|[\]().{}]/g; + +function pad(value, fill, width) { + var sign = value < 0 ? "-" : "", + string = (sign ? -value : value) + "", + length = string.length; + return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); +} + +function requote(s) { + return s.replace(requoteRe, "\\$&"); +} + +function formatRe(names) { + return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); +} + +function formatLookup(names) { + var map = {}, i = -1, n = names.length; + while (++i < n) map[names[i].toLowerCase()] = i; + return map; +} + +function parseWeekdayNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.w = +n[0], i + n[0].length) : -1; +} + +function parseWeekdayNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 1)); + return n ? (d.u = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberSunday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.U = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberISO(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.V = +n[0], i + n[0].length) : -1; +} + +function parseWeekNumberMonday(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.W = +n[0], i + n[0].length) : -1; +} + +function parseFullYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 4)); + return n ? (d.y = +n[0], i + n[0].length) : -1; +} + +function parseYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; +} + +function parseZone(d, string, i) { + var n = /^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(string.slice(i, i + 6)); + return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1; +} + +function parseMonthNumber(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.m = n[0] - 1, i + n[0].length) : -1; +} + +function parseDayOfMonth(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.d = +n[0], i + n[0].length) : -1; +} + +function parseDayOfYear(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; +} + +function parseHour24(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.H = +n[0], i + n[0].length) : -1; +} + +function parseMinutes(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.M = +n[0], i + n[0].length) : -1; +} + +function parseSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 2)); + return n ? (d.S = +n[0], i + n[0].length) : -1; +} + +function parseMilliseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 3)); + return n ? (d.L = +n[0], i + n[0].length) : -1; +} + +function parseMicroseconds(d, string, i) { + var n = numberRe.exec(string.slice(i, i + 6)); + return n ? (d.L = Math.floor(n[0] / 1000), i + n[0].length) : -1; +} + +function parseLiteralPercent(d, string, i) { + var n = percentRe.exec(string.slice(i, i + 1)); + return n ? i + n[0].length : -1; +} + +function parseUnixTimestamp(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.Q = +n[0], i + n[0].length) : -1; +} + +function parseUnixTimestampSeconds(d, string, i) { + var n = numberRe.exec(string.slice(i)); + return n ? (d.Q = (+n[0]) * 1000, i + n[0].length) : -1; +} + +function formatDayOfMonth(d, p) { + return pad(d.getDate(), p, 2); +} + +function formatHour24(d, p) { + return pad(d.getHours(), p, 2); +} + +function formatHour12(d, p) { + return pad(d.getHours() % 12 || 12, p, 2); +} + +function formatDayOfYear(d, p) { + return pad(1 + d3Time.timeDay.count(d3Time.timeYear(d), d), p, 3); +} + +function formatMilliseconds(d, p) { + return pad(d.getMilliseconds(), p, 3); +} + +function formatMicroseconds(d, p) { + return formatMilliseconds(d, p) + "000"; +} + +function formatMonthNumber(d, p) { + return pad(d.getMonth() + 1, p, 2); +} + +function formatMinutes(d, p) { + return pad(d.getMinutes(), p, 2); +} + +function formatSeconds(d, p) { + return pad(d.getSeconds(), p, 2); +} + +function formatWeekdayNumberMonday(d) { + var day = d.getDay(); + return day === 0 ? 7 : day; +} + +function formatWeekNumberSunday(d, p) { + return pad(d3Time.timeSunday.count(d3Time.timeYear(d), d), p, 2); +} + +function formatWeekNumberISO(d, p) { + var day = d.getDay(); + d = (day >= 4 || day === 0) ? d3Time.timeThursday(d) : d3Time.timeThursday.ceil(d); + return pad(d3Time.timeThursday.count(d3Time.timeYear(d), d) + (d3Time.timeYear(d).getDay() === 4), p, 2); +} + +function formatWeekdayNumberSunday(d) { + return d.getDay(); +} + +function formatWeekNumberMonday(d, p) { + return pad(d3Time.timeMonday.count(d3Time.timeYear(d), d), p, 2); +} + +function formatYear(d, p) { + return pad(d.getFullYear() % 100, p, 2); +} + +function formatFullYear(d, p) { + return pad(d.getFullYear() % 10000, p, 4); +} + +function formatZone(d) { + var z = d.getTimezoneOffset(); + return (z > 0 ? "-" : (z *= -1, "+")) + + pad(z / 60 | 0, "0", 2) + + pad(z % 60, "0", 2); +} + +function formatUTCDayOfMonth(d, p) { + return pad(d.getUTCDate(), p, 2); +} + +function formatUTCHour24(d, p) { + return pad(d.getUTCHours(), p, 2); +} + +function formatUTCHour12(d, p) { + return pad(d.getUTCHours() % 12 || 12, p, 2); +} + +function formatUTCDayOfYear(d, p) { + return pad(1 + d3Time.utcDay.count(d3Time.utcYear(d), d), p, 3); +} + +function formatUTCMilliseconds(d, p) { + return pad(d.getUTCMilliseconds(), p, 3); +} + +function formatUTCMicroseconds(d, p) { + return formatUTCMilliseconds(d, p) + "000"; +} + +function formatUTCMonthNumber(d, p) { + return pad(d.getUTCMonth() + 1, p, 2); +} + +function formatUTCMinutes(d, p) { + return pad(d.getUTCMinutes(), p, 2); +} + +function formatUTCSeconds(d, p) { + return pad(d.getUTCSeconds(), p, 2); +} + +function formatUTCWeekdayNumberMonday(d) { + var dow = d.getUTCDay(); + return dow === 0 ? 7 : dow; +} + +function formatUTCWeekNumberSunday(d, p) { + return pad(d3Time.utcSunday.count(d3Time.utcYear(d), d), p, 2); +} + +function formatUTCWeekNumberISO(d, p) { + var day = d.getUTCDay(); + d = (day >= 4 || day === 0) ? d3Time.utcThursday(d) : d3Time.utcThursday.ceil(d); + return pad(d3Time.utcThursday.count(d3Time.utcYear(d), d) + (d3Time.utcYear(d).getUTCDay() === 4), p, 2); +} + +function formatUTCWeekdayNumberSunday(d) { + return d.getUTCDay(); +} + +function formatUTCWeekNumberMonday(d, p) { + return pad(d3Time.utcMonday.count(d3Time.utcYear(d), d), p, 2); +} + +function formatUTCYear(d, p) { + return pad(d.getUTCFullYear() % 100, p, 2); +} + +function formatUTCFullYear(d, p) { + return pad(d.getUTCFullYear() % 10000, p, 4); +} + +function formatUTCZone() { + return "+0000"; +} + +function formatLiteralPercent() { + return "%"; +} + +function formatUnixTimestamp(d) { + return +d; +} + +function formatUnixTimestampSeconds(d) { + return Math.floor(+d / 1000); +} + +var locale; + + + + + +defaultLocale({ + dateTime: "%x, %X", + date: "%-m/%-d/%Y", + time: "%-I:%M:%S %p", + periods: ["AM", "PM"], + days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], + shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], + months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], + shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] +}); + +function defaultLocale(definition) { + locale = formatLocale(definition); + exports.timeFormat = locale.format; + exports.timeParse = locale.parse; + exports.utcFormat = locale.utcFormat; + exports.utcParse = locale.utcParse; + return locale; +} + +var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; + +function formatIsoNative(date) { + return date.toISOString(); +} + +var formatIso = Date.prototype.toISOString + ? formatIsoNative + : exports.utcFormat(isoSpecifier); + +function parseIsoNative(string) { + var date = new Date(string); + return isNaN(date) ? null : date; +} + +var parseIso = +new Date("2000-01-01T00:00:00.000Z") + ? parseIsoNative + : exports.utcParse(isoSpecifier); + +exports.timeFormatDefaultLocale = defaultLocale; +exports.timeFormatLocale = formatLocale; +exports.isoFormat = formatIso; +exports.isoParse = parseIso; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-time":48}],48:[function(require,module,exports){ +// https://d3js.org/d3-time/ Version 1.0.8. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var t0 = new Date; +var t1 = new Date; + +function newInterval(floori, offseti, count, field) { + + function interval(date) { + return floori(date = new Date(+date)), date; + } + + interval.floor = interval; + + interval.ceil = function(date) { + return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date; + }; + + interval.round = function(date) { + var d0 = interval(date), + d1 = interval.ceil(date); + return date - d0 < d1 - date ? d0 : d1; + }; + + interval.offset = function(date, step) { + return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; + }; + + interval.range = function(start, stop, step) { + var range = [], previous; + start = interval.ceil(start); + step = step == null ? 1 : Math.floor(step); + if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date + do range.push(previous = new Date(+start)), offseti(start, step), floori(start); + while (previous < start && start < stop); + return range; + }; + + interval.filter = function(test) { + return newInterval(function(date) { + if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1); + }, function(date, step) { + if (date >= date) { + if (step < 0) while (++step <= 0) { + while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty + } else while (--step >= 0) { + while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty + } + } + }); + }; + + if (count) { + interval.count = function(start, end) { + t0.setTime(+start), t1.setTime(+end); + floori(t0), floori(t1); + return Math.floor(count(t0, t1)); + }; + + interval.every = function(step) { + step = Math.floor(step); + return !isFinite(step) || !(step > 0) ? null + : !(step > 1) ? interval + : interval.filter(field + ? function(d) { return field(d) % step === 0; } + : function(d) { return interval.count(0, d) % step === 0; }); + }; + } + + return interval; +} + +var millisecond = newInterval(function() { + // noop +}, function(date, step) { + date.setTime(+date + step); +}, function(start, end) { + return end - start; +}); + +// An optimized implementation for this simple case. +millisecond.every = function(k) { + k = Math.floor(k); + if (!isFinite(k) || !(k > 0)) return null; + if (!(k > 1)) return millisecond; + return newInterval(function(date) { + date.setTime(Math.floor(date / k) * k); + }, function(date, step) { + date.setTime(+date + step * k); + }, function(start, end) { + return (end - start) / k; + }); +}; + +var milliseconds = millisecond.range; + +var durationSecond = 1e3; +var durationMinute = 6e4; +var durationHour = 36e5; +var durationDay = 864e5; +var durationWeek = 6048e5; + +var second = newInterval(function(date) { + date.setTime(Math.floor(date / durationSecond) * durationSecond); +}, function(date, step) { + date.setTime(+date + step * durationSecond); +}, function(start, end) { + return (end - start) / durationSecond; +}, function(date) { + return date.getUTCSeconds(); +}); + +var seconds = second.range; + +var minute = newInterval(function(date) { + date.setTime(Math.floor(date / durationMinute) * durationMinute); +}, function(date, step) { + date.setTime(+date + step * durationMinute); +}, function(start, end) { + return (end - start) / durationMinute; +}, function(date) { + return date.getMinutes(); +}); + +var minutes = minute.range; + +var hour = newInterval(function(date) { + var offset = date.getTimezoneOffset() * durationMinute % durationHour; + if (offset < 0) offset += durationHour; + date.setTime(Math.floor((+date - offset) / durationHour) * durationHour + offset); +}, function(date, step) { + date.setTime(+date + step * durationHour); +}, function(start, end) { + return (end - start) / durationHour; +}, function(date) { + return date.getHours(); +}); + +var hours = hour.range; + +var day = newInterval(function(date) { + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setDate(date.getDate() + step); +}, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay; +}, function(date) { + return date.getDate() - 1; +}); + +var days = day.range; + +function weekday(i) { + return newInterval(function(date) { + date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setDate(date.getDate() + step * 7); + }, function(start, end) { + return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek; + }); +} + +var sunday = weekday(0); +var monday = weekday(1); +var tuesday = weekday(2); +var wednesday = weekday(3); +var thursday = weekday(4); +var friday = weekday(5); +var saturday = weekday(6); + +var sundays = sunday.range; +var mondays = monday.range; +var tuesdays = tuesday.range; +var wednesdays = wednesday.range; +var thursdays = thursday.range; +var fridays = friday.range; +var saturdays = saturday.range; + +var month = newInterval(function(date) { + date.setDate(1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setMonth(date.getMonth() + step); +}, function(start, end) { + return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; +}, function(date) { + return date.getMonth(); +}); + +var months = month.range; + +var year = newInterval(function(date) { + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); +}, function(date, step) { + date.setFullYear(date.getFullYear() + step); +}, function(start, end) { + return end.getFullYear() - start.getFullYear(); +}, function(date) { + return date.getFullYear(); +}); + +// An optimized implementation for this simple case. +year.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setFullYear(Math.floor(date.getFullYear() / k) * k); + date.setMonth(0, 1); + date.setHours(0, 0, 0, 0); + }, function(date, step) { + date.setFullYear(date.getFullYear() + step * k); + }); +}; + +var years = year.range; + +var utcMinute = newInterval(function(date) { + date.setUTCSeconds(0, 0); +}, function(date, step) { + date.setTime(+date + step * durationMinute); +}, function(start, end) { + return (end - start) / durationMinute; +}, function(date) { + return date.getUTCMinutes(); +}); + +var utcMinutes = utcMinute.range; + +var utcHour = newInterval(function(date) { + date.setUTCMinutes(0, 0, 0); +}, function(date, step) { + date.setTime(+date + step * durationHour); +}, function(start, end) { + return (end - start) / durationHour; +}, function(date) { + return date.getUTCHours(); +}); + +var utcHours = utcHour.range; + +var utcDay = newInterval(function(date) { + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCDate(date.getUTCDate() + step); +}, function(start, end) { + return (end - start) / durationDay; +}, function(date) { + return date.getUTCDate() - 1; +}); + +var utcDays = utcDay.range; + +function utcWeekday(i) { + return newInterval(function(date) { + date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCDate(date.getUTCDate() + step * 7); + }, function(start, end) { + return (end - start) / durationWeek; + }); +} + +var utcSunday = utcWeekday(0); +var utcMonday = utcWeekday(1); +var utcTuesday = utcWeekday(2); +var utcWednesday = utcWeekday(3); +var utcThursday = utcWeekday(4); +var utcFriday = utcWeekday(5); +var utcSaturday = utcWeekday(6); + +var utcSundays = utcSunday.range; +var utcMondays = utcMonday.range; +var utcTuesdays = utcTuesday.range; +var utcWednesdays = utcWednesday.range; +var utcThursdays = utcThursday.range; +var utcFridays = utcFriday.range; +var utcSaturdays = utcSaturday.range; + +var utcMonth = newInterval(function(date) { + date.setUTCDate(1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCMonth(date.getUTCMonth() + step); +}, function(start, end) { + return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; +}, function(date) { + return date.getUTCMonth(); +}); + +var utcMonths = utcMonth.range; + +var utcYear = newInterval(function(date) { + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); +}, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step); +}, function(start, end) { + return end.getUTCFullYear() - start.getUTCFullYear(); +}, function(date) { + return date.getUTCFullYear(); +}); + +// An optimized implementation for this simple case. +utcYear.every = function(k) { + return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) { + date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k); + date.setUTCMonth(0, 1); + date.setUTCHours(0, 0, 0, 0); + }, function(date, step) { + date.setUTCFullYear(date.getUTCFullYear() + step * k); + }); +}; + +var utcYears = utcYear.range; + +exports.timeInterval = newInterval; +exports.timeMillisecond = millisecond; +exports.timeMilliseconds = milliseconds; +exports.utcMillisecond = millisecond; +exports.utcMilliseconds = milliseconds; +exports.timeSecond = second; +exports.timeSeconds = seconds; +exports.utcSecond = second; +exports.utcSeconds = seconds; +exports.timeMinute = minute; +exports.timeMinutes = minutes; +exports.timeHour = hour; +exports.timeHours = hours; +exports.timeDay = day; +exports.timeDays = days; +exports.timeWeek = sunday; +exports.timeWeeks = sundays; +exports.timeSunday = sunday; +exports.timeSundays = sundays; +exports.timeMonday = monday; +exports.timeMondays = mondays; +exports.timeTuesday = tuesday; +exports.timeTuesdays = tuesdays; +exports.timeWednesday = wednesday; +exports.timeWednesdays = wednesdays; +exports.timeThursday = thursday; +exports.timeThursdays = thursdays; +exports.timeFriday = friday; +exports.timeFridays = fridays; +exports.timeSaturday = saturday; +exports.timeSaturdays = saturdays; +exports.timeMonth = month; +exports.timeMonths = months; +exports.timeYear = year; +exports.timeYears = years; +exports.utcMinute = utcMinute; +exports.utcMinutes = utcMinutes; +exports.utcHour = utcHour; +exports.utcHours = utcHours; +exports.utcDay = utcDay; +exports.utcDays = utcDays; +exports.utcWeek = utcSunday; +exports.utcWeeks = utcSundays; +exports.utcSunday = utcSunday; +exports.utcSundays = utcSundays; +exports.utcMonday = utcMonday; +exports.utcMondays = utcMondays; +exports.utcTuesday = utcTuesday; +exports.utcTuesdays = utcTuesdays; +exports.utcWednesday = utcWednesday; +exports.utcWednesdays = utcWednesdays; +exports.utcThursday = utcThursday; +exports.utcThursdays = utcThursdays; +exports.utcFriday = utcFriday; +exports.utcFridays = utcFridays; +exports.utcSaturday = utcSaturday; +exports.utcSaturdays = utcSaturdays; +exports.utcMonth = utcMonth; +exports.utcMonths = utcMonths; +exports.utcYear = utcYear; +exports.utcYears = utcYears; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],49:[function(require,module,exports){ +// https://d3js.org/d3-timer/ Version 1.0.7. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var frame = 0; +var timeout = 0; +var interval = 0; +var pokeDelay = 1000; +var taskHead; +var taskTail; +var clockLast = 0; +var clockNow = 0; +var clockSkew = 0; +var clock = typeof performance === "object" && performance.now ? performance : Date; +var setFrame = typeof window === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) { setTimeout(f, 17); }; + +function now() { + return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew); +} + +function clearNow() { + clockNow = 0; +} + +function Timer() { + this._call = + this._time = + this._next = null; +} + +Timer.prototype = timer.prototype = { + constructor: Timer, + restart: function(callback, delay, time) { + if (typeof callback !== "function") throw new TypeError("callback is not a function"); + time = (time == null ? now() : +time) + (delay == null ? 0 : +delay); + if (!this._next && taskTail !== this) { + if (taskTail) taskTail._next = this; + else taskHead = this; + taskTail = this; + } + this._call = callback; + this._time = time; + sleep(); + }, + stop: function() { + if (this._call) { + this._call = null; + this._time = Infinity; + sleep(); + } + } +}; + +function timer(callback, delay, time) { + var t = new Timer; + t.restart(callback, delay, time); + return t; +} + +function timerFlush() { + now(); // Get the current time, if not already set. + ++frame; // Pretend we’ve set an alarm, if we haven’t already. + var t = taskHead, e; + while (t) { + if ((e = clockNow - t._time) >= 0) t._call.call(null, e); + t = t._next; + } + --frame; +} + +function wake() { + clockNow = (clockLast = clock.now()) + clockSkew; + frame = timeout = 0; + try { + timerFlush(); + } finally { + frame = 0; + nap(); + clockNow = 0; + } +} + +function poke() { + var now = clock.now(), delay = now - clockLast; + if (delay > pokeDelay) clockSkew -= delay, clockLast = now; +} + +function nap() { + var t0, t1 = taskHead, t2, time = Infinity; + while (t1) { + if (t1._call) { + if (time > t1._time) time = t1._time; + t0 = t1, t1 = t1._next; + } else { + t2 = t1._next, t1._next = null; + t1 = t0 ? t0._next = t2 : taskHead = t2; + } + } + taskTail = t0; + sleep(time); +} + +function sleep(time) { + if (frame) return; // Soonest alarm already set, or will be. + if (timeout) timeout = clearTimeout(timeout); + var delay = time - clockNow; // Strictly less than if we recomputed clockNow. + if (delay > 24) { + if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew); + if (interval) interval = clearInterval(interval); + } else { + if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay); + frame = 1, setFrame(wake); + } +} + +var timeout$1 = function(callback, delay, time) { + var t = new Timer; + delay = delay == null ? 0 : +delay; + t.restart(function(elapsed) { + t.stop(); + callback(elapsed + delay); + }, delay, time); + return t; +}; + +var interval$1 = function(callback, delay, time) { + var t = new Timer, total = delay; + if (delay == null) return t.restart(callback, delay, time), t; + delay = +delay, time = time == null ? now() : +time; + t.restart(function tick(elapsed) { + elapsed += total; + t.restart(tick, total += delay, time); + callback(elapsed); + }, delay, time); + return t; +}; + +exports.now = now; +exports.timer = timer; +exports.timerFlush = timerFlush; +exports.timeout = timeout$1; +exports.interval = interval$1; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],50:[function(require,module,exports){ +// d3.tip +// Copyright (c) 2013 Justin Palmer +// +// Tooltips for d3.js SVG visualizations + +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module with d3 as a dependency. + define(['d3'], factory) + } else if (typeof module === 'object' && module.exports) { + // CommonJS + var d3 = require('d3') + module.exports = factory(d3) + } else { + // Browser global. + root.d3.tip = factory(root.d3) + } +}(this, function (d3) { + + // Public - contructs a new tooltip + // + // Returns a tip + return function() { + var direction = d3_tip_direction, + offset = d3_tip_offset, + html = d3_tip_html, + node = initNode(), + svg = null, + point = null, + target = null + + function tip(vis) { + svg = getSVGNode(vis) + point = svg.createSVGPoint() + document.body.appendChild(node) + } + + // Public - show the tooltip on the screen + // + // Returns a tip + tip.show = function() { + var args = Array.prototype.slice.call(arguments) + if(args[args.length - 1] instanceof SVGElement) target = args.pop() + + var content = html.apply(this, args), + poffset = offset.apply(this, args), + dir = direction.apply(this, args), + nodel = getNodeEl(), + i = directions.length, + coords, + scrollTop = document.documentElement.scrollTop || document.body.scrollTop, + scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft + + nodel.html(content) + .style('opacity', 1).style('pointer-events', 'all') + + while(i--) nodel.classed(directions[i], false) + coords = direction_callbacks.get(dir).apply(this) + nodel.classed(dir, true) + .style('top', (coords.top + poffset[0]) + scrollTop + 'px') + .style('left', (coords.left + poffset[1]) + scrollLeft + 'px') + + return tip; + }; + + // Public - hide the tooltip + // + // Returns a tip + tip.hide = function() { + var nodel = getNodeEl() + nodel.style('opacity', 0).style('pointer-events', 'none') + return tip + } + + // Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value. + // + // n - name of the attribute + // v - value of the attribute + // + // Returns tip or attribute value + tip.attr = function(n, v) { + if (arguments.length < 2 && typeof n === 'string') { + return getNodeEl().attr(n) + } else { + var args = Array.prototype.slice.call(arguments) + d3.selection.prototype.attr.apply(getNodeEl(), args) + } + + return tip + } + + // Public: Proxy style calls to the d3 tip container. Sets or gets a style value. + // + // n - name of the property + // v - value of the property + // + // Returns tip or style property value + tip.style = function(n, v) { + if (arguments.length < 2 && typeof n === 'string') { + return getNodeEl().style(n) + } else { + var args = Array.prototype.slice.call(arguments) + d3.selection.prototype.style.apply(getNodeEl(), args) + } + + return tip + } + + // Public: Set or get the direction of the tooltip + // + // v - One of n(north), s(south), e(east), or w(west), nw(northwest), + // sw(southwest), ne(northeast) or se(southeast) + // + // Returns tip or direction + tip.direction = function(v) { + if (!arguments.length) return direction + direction = v == null ? v : functor(v) + + return tip + } + + // Public: Sets or gets the offset of the tip + // + // v - Array of [x, y] offset + // + // Returns offset or + tip.offset = function(v) { + if (!arguments.length) return offset + offset = v == null ? v : functor(v) + + return tip + } + + // Public: sets or gets the html value of the tooltip + // + // v - String value of the tip + // + // Returns html value or tip + tip.html = function(v) { + if (!arguments.length) return html + html = v == null ? v : functor(v) + + return tip + } + + // Public: destroys the tooltip and removes it from the DOM + // + // Returns a tip + tip.destroy = function() { + if(node) { + getNodeEl().remove(); + node = null; + } + return tip; + } + + function d3_tip_direction() { return 'n' } + function d3_tip_offset() { return [0, 0] } + function d3_tip_html() { return ' ' } + + var direction_callbacks = d3.map({ + n: direction_n, + s: direction_s, + e: direction_e, + w: direction_w, + nw: direction_nw, + ne: direction_ne, + sw: direction_sw, + se: direction_se + }), + + directions = direction_callbacks.keys() + + function direction_n() { + var bbox = getScreenBBox() + return { + top: bbox.n.y - node.offsetHeight, + left: bbox.n.x - node.offsetWidth / 2 + } + } + + function direction_s() { + var bbox = getScreenBBox() + return { + top: bbox.s.y, + left: bbox.s.x - node.offsetWidth / 2 + } + } + + function direction_e() { + var bbox = getScreenBBox() + return { + top: bbox.e.y - node.offsetHeight / 2, + left: bbox.e.x + } + } + + function direction_w() { + var bbox = getScreenBBox() + return { + top: bbox.w.y - node.offsetHeight / 2, + left: bbox.w.x - node.offsetWidth + } + } + + function direction_nw() { + var bbox = getScreenBBox() + return { + top: bbox.nw.y - node.offsetHeight, + left: bbox.nw.x - node.offsetWidth + } + } + + function direction_ne() { + var bbox = getScreenBBox() + return { + top: bbox.ne.y - node.offsetHeight, + left: bbox.ne.x + } + } + + function direction_sw() { + var bbox = getScreenBBox() + return { + top: bbox.sw.y, + left: bbox.sw.x - node.offsetWidth + } + } + + function direction_se() { + var bbox = getScreenBBox() + return { + top: bbox.se.y, + left: bbox.e.x + } + } + + function initNode() { + var node = d3.select(document.createElement('div')); + node.style('position', 'absolute').style('top', 0).style('opacity', 0) + .style('pointer-events', 'none').style('box-sizing', 'border-box') + + return node.node() + } + + function getSVGNode(el) { + el = el.node() + if(el.tagName.toLowerCase() === 'svg') + return el + + return el.ownerSVGElement + } + + function getNodeEl() { + if(node === null) { + node = initNode(); + // re-add node to DOM + document.body.appendChild(node); + }; + return d3.select(node); + } + + // Private - gets the screen coordinates of a shape + // + // Given a shape on the screen, will return an SVGPoint for the directions + // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest), + // sw(southwest). + // + // +-+-+ + // | | + // + + + // | | + // +-+-+ + // + // Returns an Object {n, s, e, w, nw, sw, ne, se} + function getScreenBBox() { + var targetel = target || d3.event.target; + + while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) { + targetel = targetel.parentNode; + } + + var bbox = {}, + matrix = targetel.getScreenCTM(), + tbbox = targetel.getBBox(), + width = tbbox.width, + height = tbbox.height, + x = tbbox.x, + y = tbbox.y + + point.x = x + point.y = y + bbox.nw = point.matrixTransform(matrix) + point.x += width + bbox.ne = point.matrixTransform(matrix) + point.y += height + bbox.se = point.matrixTransform(matrix) + point.x -= width + bbox.sw = point.matrixTransform(matrix) + point.y -= height / 2 + bbox.w = point.matrixTransform(matrix) + point.x += width + bbox.e = point.matrixTransform(matrix) + point.x -= width / 2 + point.y -= height / 2 + bbox.n = point.matrixTransform(matrix) + point.y += height + bbox.s = point.matrixTransform(matrix) + + return bbox + } + + // Private - replace D3JS 3.X d3.functor() function + function functor(v) { + return typeof v === "function" ? v : function() { + return v + } + } + + return tip + }; + +})); + +},{"d3":54}],51:[function(require,module,exports){ +// https://d3js.org/d3-transition/ Version 1.1.1. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-selection'), require('d3-dispatch'), require('d3-timer'), require('d3-interpolate'), require('d3-color'), require('d3-ease')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-selection', 'd3-dispatch', 'd3-timer', 'd3-interpolate', 'd3-color', 'd3-ease'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3,global.d3)); +}(this, (function (exports,d3Selection,d3Dispatch,d3Timer,d3Interpolate,d3Color,d3Ease) { 'use strict'; + +var emptyOn = d3Dispatch.dispatch("start", "end", "interrupt"); +var emptyTween = []; + +var CREATED = 0; +var SCHEDULED = 1; +var STARTING = 2; +var STARTED = 3; +var RUNNING = 4; +var ENDING = 5; +var ENDED = 6; + +var schedule = function(node, name, id, index, group, timing) { + var schedules = node.__transition; + if (!schedules) node.__transition = {}; + else if (id in schedules) return; + create(node, id, { + name: name, + index: index, // For context during callback. + group: group, // For context during callback. + on: emptyOn, + tween: emptyTween, + time: timing.time, + delay: timing.delay, + duration: timing.duration, + ease: timing.ease, + timer: null, + state: CREATED + }); +}; + +function init(node, id) { + var schedule = get(node, id); + if (schedule.state > CREATED) throw new Error("too late; already scheduled"); + return schedule; +} + +function set(node, id) { + var schedule = get(node, id); + if (schedule.state > STARTING) throw new Error("too late; already started"); + return schedule; +} + +function get(node, id) { + var schedule = node.__transition; + if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found"); + return schedule; +} + +function create(node, id, self) { + var schedules = node.__transition, + tween; + + // Initialize the self timer when the transition is created. + // Note the actual delay is not known until the first callback! + schedules[id] = self; + self.timer = d3Timer.timer(schedule, 0, self.time); + + function schedule(elapsed) { + self.state = SCHEDULED; + self.timer.restart(start, self.delay, self.time); + + // If the elapsed delay is less than our first sleep, start immediately. + if (self.delay <= elapsed) start(elapsed - self.delay); + } + + function start(elapsed) { + var i, j, n, o; + + // If the state is not SCHEDULED, then we previously errored on start. + if (self.state !== SCHEDULED) return stop(); + + for (i in schedules) { + o = schedules[i]; + if (o.name !== self.name) continue; + + // While this element already has a starting transition during this frame, + // defer starting an interrupting transition until that transition has a + // chance to tick (and possibly end); see d3/d3-transition#54! + if (o.state === STARTED) return d3Timer.timeout(start); + + // Interrupt the active transition, if any. + // Dispatch the interrupt event. + if (o.state === RUNNING) { + o.state = ENDED; + o.timer.stop(); + o.on.call("interrupt", node, node.__data__, o.index, o.group); + delete schedules[i]; + } + + // Cancel any pre-empted transitions. No interrupt event is dispatched + // because the cancelled transitions never started. Note that this also + // removes this transition from the pending list! + else if (+i < id) { + o.state = ENDED; + o.timer.stop(); + delete schedules[i]; + } + } + + // Defer the first tick to end of the current frame; see d3/d3#1576. + // Note the transition may be canceled after start and before the first tick! + // Note this must be scheduled before the start event; see d3/d3-transition#16! + // Assuming this is successful, subsequent callbacks go straight to tick. + d3Timer.timeout(function() { + if (self.state === STARTED) { + self.state = RUNNING; + self.timer.restart(tick, self.delay, self.time); + tick(elapsed); + } + }); + + // Dispatch the start event. + // Note this must be done before the tween are initialized. + self.state = STARTING; + self.on.call("start", node, node.__data__, self.index, self.group); + if (self.state !== STARTING) return; // interrupted + self.state = STARTED; + + // Initialize the tween, deleting null tween. + tween = new Array(n = self.tween.length); + for (i = 0, j = -1; i < n; ++i) { + if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) { + tween[++j] = o; + } + } + tween.length = j + 1; + } + + function tick(elapsed) { + var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), + i = -1, + n = tween.length; + + while (++i < n) { + tween[i].call(null, t); + } + + // Dispatch the end event. + if (self.state === ENDING) { + self.on.call("end", node, node.__data__, self.index, self.group); + stop(); + } + } + + function stop() { + self.state = ENDED; + self.timer.stop(); + delete schedules[id]; + for (var i in schedules) return; // eslint-disable-line no-unused-vars + delete node.__transition; + } +} + +var interrupt = function(node, name) { + var schedules = node.__transition, + schedule, + active, + empty = true, + i; + + if (!schedules) return; + + name = name == null ? null : name + ""; + + for (i in schedules) { + if ((schedule = schedules[i]).name !== name) { empty = false; continue; } + active = schedule.state > STARTING && schedule.state < ENDING; + schedule.state = ENDED; + schedule.timer.stop(); + if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group); + delete schedules[i]; + } + + if (empty) delete node.__transition; +}; + +var selection_interrupt = function(name) { + return this.each(function() { + interrupt(this, name); + }); +}; + +function tweenRemove(id, name) { + var tween0, tween1; + return function() { + var schedule = set(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = tween0 = tween; + for (var i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1 = tween1.slice(); + tween1.splice(i, 1); + break; + } + } + } + + schedule.tween = tween1; + }; +} + +function tweenFunction(id, name, value) { + var tween0, tween1; + if (typeof value !== "function") throw new Error; + return function() { + var schedule = set(this, id), + tween = schedule.tween; + + // If this node shared tween with the previous node, + // just assign the updated shared tween and we’re done! + // Otherwise, copy-on-write. + if (tween !== tween0) { + tween1 = (tween0 = tween).slice(); + for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) { + if (tween1[i].name === name) { + tween1[i] = t; + break; + } + } + if (i === n) tween1.push(t); + } + + schedule.tween = tween1; + }; +} + +var transition_tween = function(name, value) { + var id = this._id; + + name += ""; + + if (arguments.length < 2) { + var tween = get(this.node(), id).tween; + for (var i = 0, n = tween.length, t; i < n; ++i) { + if ((t = tween[i]).name === name) { + return t.value; + } + } + return null; + } + + return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value)); +}; + +function tweenValue(transition, name, value) { + var id = transition._id; + + transition.each(function() { + var schedule = set(this, id); + (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments); + }); + + return function(node) { + return get(node, id).value[name]; + }; +} + +var interpolate = function(a, b) { + var c; + return (typeof b === "number" ? d3Interpolate.interpolateNumber + : b instanceof d3Color.color ? d3Interpolate.interpolateRgb + : (c = d3Color.color(b)) ? (b = c, d3Interpolate.interpolateRgb) + : d3Interpolate.interpolateString)(a, b); +}; + +function attrRemove(name) { + return function() { + this.removeAttribute(name); + }; +} + +function attrRemoveNS(fullname) { + return function() { + this.removeAttributeNS(fullname.space, fullname.local); + }; +} + +function attrConstant(name, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function attrConstantNS(fullname, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function attrFunction(name, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttribute(name); + value0 = this.getAttribute(name); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +function attrFunctionNS(fullname, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0, value1 = value(this); + if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local); + value0 = this.getAttributeNS(fullname.space, fullname.local); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +var transition_attr = function(name, value) { + var fullname = d3Selection.namespace(name), i = fullname === "transform" ? d3Interpolate.interpolateTransformSvg : interpolate; + return this.attrTween(name, typeof value === "function" + ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) + : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) + : (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value + "")); +}; + +function attrTweenNS(fullname, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttributeNS(fullname.space, fullname.local, i(t)); + }; + } + tween._value = value; + return tween; +} + +function attrTween(name, value) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.setAttribute(name, i(t)); + }; + } + tween._value = value; + return tween; +} + +var transition_attrTween = function(name, value) { + var key = "attr." + name; + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + var fullname = d3Selection.namespace(name); + return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value)); +}; + +function delayFunction(id, value) { + return function() { + init(this, id).delay = +value.apply(this, arguments); + }; +} + +function delayConstant(id, value) { + return value = +value, function() { + init(this, id).delay = value; + }; +} + +var transition_delay = function(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? delayFunction + : delayConstant)(id, value)) + : get(this.node(), id).delay; +}; + +function durationFunction(id, value) { + return function() { + set(this, id).duration = +value.apply(this, arguments); + }; +} + +function durationConstant(id, value) { + return value = +value, function() { + set(this, id).duration = value; + }; +} + +var transition_duration = function(value) { + var id = this._id; + + return arguments.length + ? this.each((typeof value === "function" + ? durationFunction + : durationConstant)(id, value)) + : get(this.node(), id).duration; +}; + +function easeConstant(id, value) { + if (typeof value !== "function") throw new Error; + return function() { + set(this, id).ease = value; + }; +} + +var transition_ease = function(value) { + var id = this._id; + + return arguments.length + ? this.each(easeConstant(id, value)) + : get(this.node(), id).ease; +}; + +var transition_filter = function(match) { + if (typeof match !== "function") match = d3Selection.matcher(match); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) { + if ((node = group[i]) && match.call(node, node.__data__, i, group)) { + subgroup.push(node); + } + } + } + + return new Transition(subgroups, this._parents, this._name, this._id); +}; + +var transition_merge = function(transition) { + if (transition._id !== this._id) throw new Error; + + for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) { + for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) { + if (node = group0[i] || group1[i]) { + merge[i] = node; + } + } + } + + for (; j < m0; ++j) { + merges[j] = groups0[j]; + } + + return new Transition(merges, this._parents, this._name, this._id); +}; + +function start(name) { + return (name + "").trim().split(/^|\s+/).every(function(t) { + var i = t.indexOf("."); + if (i >= 0) t = t.slice(0, i); + return !t || t === "start"; + }); +} + +function onFunction(id, name, listener) { + var on0, on1, sit = start(name) ? init : set; + return function() { + var schedule = sit(this, id), + on = schedule.on; + + // If this node shared a dispatch with the previous node, + // just assign the updated shared dispatch and we’re done! + // Otherwise, copy-on-write. + if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener); + + schedule.on = on1; + }; +} + +var transition_on = function(name, listener) { + var id = this._id; + + return arguments.length < 2 + ? get(this.node(), id).on.on(name) + : this.each(onFunction(id, name, listener)); +}; + +function removeFunction(id) { + return function() { + var parent = this.parentNode; + for (var i in this.__transition) if (+i !== id) return; + if (parent) parent.removeChild(this); + }; +} + +var transition_remove = function() { + return this.on("end.remove", removeFunction(this._id)); +}; + +var transition_select = function(select) { + var name = this._name, + id = this._id; + + if (typeof select !== "function") select = d3Selection.selector(select); + + for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) { + if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) { + if ("__data__" in node) subnode.__data__ = node.__data__; + subgroup[i] = subnode; + schedule(subgroup[i], name, id, i, subgroup, get(node, id)); + } + } + } + + return new Transition(subgroups, this._parents, name, id); +}; + +var transition_selectAll = function(select) { + var name = this._name, + id = this._id; + + if (typeof select !== "function") select = d3Selection.selectorAll(select); + + for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + for (var children = select.call(node, node.__data__, i, group), child, inherit = get(node, id), k = 0, l = children.length; k < l; ++k) { + if (child = children[k]) { + schedule(child, name, id, k, children, inherit); + } + } + subgroups.push(children); + parents.push(node); + } + } + } + + return new Transition(subgroups, parents, name, id); +}; + +var Selection = d3Selection.selection.prototype.constructor; + +var transition_selection = function() { + return new Selection(this._groups, this._parents); +}; + +function styleRemove(name, interpolate$$1) { + var value00, + value10, + interpolate0; + return function() { + var value0 = d3Selection.style(this, name), + value1 = (this.style.removeProperty(name), d3Selection.style(this, name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +function styleRemoveEnd(name) { + return function() { + this.style.removeProperty(name); + }; +} + +function styleConstant(name, interpolate$$1, value1) { + var value00, + interpolate0; + return function() { + var value0 = d3Selection.style(this, name); + return value0 === value1 ? null + : value0 === value00 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value1); + }; +} + +function styleFunction(name, interpolate$$1, value) { + var value00, + value10, + interpolate0; + return function() { + var value0 = d3Selection.style(this, name), + value1 = value(this); + if (value1 == null) value1 = (this.style.removeProperty(name), d3Selection.style(this, name)); + return value0 === value1 ? null + : value0 === value00 && value1 === value10 ? interpolate0 + : interpolate0 = interpolate$$1(value00 = value0, value10 = value1); + }; +} + +var transition_style = function(name, value, priority) { + var i = (name += "") === "transform" ? d3Interpolate.interpolateTransformCss : interpolate; + return value == null ? this + .styleTween(name, styleRemove(name, i)) + .on("end.style." + name, styleRemoveEnd(name)) + : this.styleTween(name, typeof value === "function" + ? styleFunction(name, i, tweenValue(this, "style." + name, value)) + : styleConstant(name, i, value + ""), priority); +}; + +function styleTween(name, value, priority) { + function tween() { + var node = this, i = value.apply(node, arguments); + return i && function(t) { + node.style.setProperty(name, i(t), priority); + }; + } + tween._value = value; + return tween; +} + +var transition_styleTween = function(name, value, priority) { + var key = "style." + (name += ""); + if (arguments.length < 2) return (key = this.tween(key)) && key._value; + if (value == null) return this.tween(key, null); + if (typeof value !== "function") throw new Error; + return this.tween(key, styleTween(name, value, priority == null ? "" : priority)); +}; + +function textConstant(value) { + return function() { + this.textContent = value; + }; +} + +function textFunction(value) { + return function() { + var value1 = value(this); + this.textContent = value1 == null ? "" : value1; + }; +} + +var transition_text = function(value) { + return this.tween("text", typeof value === "function" + ? textFunction(tweenValue(this, "text", value)) + : textConstant(value == null ? "" : value + "")); +}; + +var transition_transition = function() { + var name = this._name, + id0 = this._id, + id1 = newId(); + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + var inherit = get(node, id0); + schedule(node, name, id1, i, group, { + time: inherit.time + inherit.delay + inherit.duration, + delay: 0, + duration: inherit.duration, + ease: inherit.ease + }); + } + } + } + + return new Transition(groups, this._parents, name, id1); +}; + +var id = 0; + +function Transition(groups, parents, name, id) { + this._groups = groups; + this._parents = parents; + this._name = name; + this._id = id; +} + +function transition(name) { + return d3Selection.selection().transition(name); +} + +function newId() { + return ++id; +} + +var selection_prototype = d3Selection.selection.prototype; + +Transition.prototype = transition.prototype = { + constructor: Transition, + select: transition_select, + selectAll: transition_selectAll, + filter: transition_filter, + merge: transition_merge, + selection: transition_selection, + transition: transition_transition, + call: selection_prototype.call, + nodes: selection_prototype.nodes, + node: selection_prototype.node, + size: selection_prototype.size, + empty: selection_prototype.empty, + each: selection_prototype.each, + on: transition_on, + attr: transition_attr, + attrTween: transition_attrTween, + style: transition_style, + styleTween: transition_styleTween, + text: transition_text, + remove: transition_remove, + tween: transition_tween, + delay: transition_delay, + duration: transition_duration, + ease: transition_ease +}; + +var defaultTiming = { + time: null, // Set on use. + delay: 0, + duration: 250, + ease: d3Ease.easeCubicInOut +}; + +function inherit(node, id) { + var timing; + while (!(timing = node.__transition) || !(timing = timing[id])) { + if (!(node = node.parentNode)) { + return defaultTiming.time = d3Timer.now(), defaultTiming; + } + } + return timing; +} + +var selection_transition = function(name) { + var id, + timing; + + if (name instanceof Transition) { + id = name._id, name = name._name; + } else { + id = newId(), (timing = defaultTiming).time = d3Timer.now(), name = name == null ? null : name + ""; + } + + for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) { + for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) { + if (node = group[i]) { + schedule(node, name, id, i, group, timing || inherit(node, id)); + } + } + } + + return new Transition(groups, this._parents, name, id); +}; + +d3Selection.selection.prototype.interrupt = selection_interrupt; +d3Selection.selection.prototype.transition = selection_transition; + +var root = [null]; + +var active = function(node, name) { + var schedules = node.__transition, + schedule, + i; + + if (schedules) { + name = name == null ? null : name + ""; + for (i in schedules) { + if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) { + return new Transition([[node]], root, name, +i); + } + } + } + + return null; +}; + +exports.transition = transition; +exports.active = active; +exports.interrupt = interrupt; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-color":28,"d3-dispatch":29,"d3-ease":32,"d3-interpolate":37,"d3-selection":45,"d3-timer":49}],52:[function(require,module,exports){ +// https://d3js.org/d3-voronoi/ Version 1.1.2. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : + typeof define === 'function' && define.amd ? define(['exports'], factory) : + (factory((global.d3 = global.d3 || {}))); +}(this, (function (exports) { 'use strict'; + +var constant = function(x) { + return function() { + return x; + }; +}; + +function x(d) { + return d[0]; +} + +function y(d) { + return d[1]; +} + +function RedBlackTree() { + this._ = null; // root node +} + +function RedBlackNode(node) { + node.U = // parent node + node.C = // color - true for red, false for black + node.L = // left node + node.R = // right node + node.P = // previous node + node.N = null; // next node +} + +RedBlackTree.prototype = { + constructor: RedBlackTree, + + insert: function(after, node) { + var parent, grandpa, uncle; + + if (after) { + node.P = after; + node.N = after.N; + if (after.N) after.N.P = node; + after.N = node; + if (after.R) { + after = after.R; + while (after.L) after = after.L; + after.L = node; + } else { + after.R = node; + } + parent = after; + } else if (this._) { + after = RedBlackFirst(this._); + node.P = null; + node.N = after; + after.P = after.L = node; + parent = after; + } else { + node.P = node.N = null; + this._ = node; + parent = null; + } + node.L = node.R = null; + node.U = parent; + node.C = true; + + after = node; + while (parent && parent.C) { + grandpa = parent.U; + if (parent === grandpa.L) { + uncle = grandpa.R; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.R) { + RedBlackRotateLeft(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateRight(this, grandpa); + } + } else { + uncle = grandpa.L; + if (uncle && uncle.C) { + parent.C = uncle.C = false; + grandpa.C = true; + after = grandpa; + } else { + if (after === parent.L) { + RedBlackRotateRight(this, parent); + after = parent; + parent = after.U; + } + parent.C = false; + grandpa.C = true; + RedBlackRotateLeft(this, grandpa); + } + } + parent = after.U; + } + this._.C = false; + }, + + remove: function(node) { + if (node.N) node.N.P = node.P; + if (node.P) node.P.N = node.N; + node.N = node.P = null; + + var parent = node.U, + sibling, + left = node.L, + right = node.R, + next, + red; + + if (!left) next = right; + else if (!right) next = left; + else next = RedBlackFirst(right); + + if (parent) { + if (parent.L === node) parent.L = next; + else parent.R = next; + } else { + this._ = next; + } + + if (left && right) { + red = next.C; + next.C = node.C; + next.L = left; + left.U = next; + if (next !== right) { + parent = next.U; + next.U = node.U; + node = next.R; + parent.L = node; + next.R = right; + right.U = next; + } else { + next.U = parent; + parent = next; + node = next.R; + } + } else { + red = node.C; + node = next; + } + + if (node) node.U = parent; + if (red) return; + if (node && node.C) { node.C = false; return; } + + do { + if (node === this._) break; + if (node === parent.L) { + sibling = parent.R; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateLeft(this, parent); + sibling = parent.R; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.R || !sibling.R.C) { + sibling.L.C = false; + sibling.C = true; + RedBlackRotateRight(this, sibling); + sibling = parent.R; + } + sibling.C = parent.C; + parent.C = sibling.R.C = false; + RedBlackRotateLeft(this, parent); + node = this._; + break; + } + } else { + sibling = parent.L; + if (sibling.C) { + sibling.C = false; + parent.C = true; + RedBlackRotateRight(this, parent); + sibling = parent.L; + } + if ((sibling.L && sibling.L.C) + || (sibling.R && sibling.R.C)) { + if (!sibling.L || !sibling.L.C) { + sibling.R.C = false; + sibling.C = true; + RedBlackRotateLeft(this, sibling); + sibling = parent.L; + } + sibling.C = parent.C; + parent.C = sibling.L.C = false; + RedBlackRotateRight(this, parent); + node = this._; + break; + } + } + sibling.C = true; + node = parent; + parent = parent.U; + } while (!node.C); + + if (node) node.C = false; + } +}; + +function RedBlackRotateLeft(tree, node) { + var p = node, + q = node.R, + parent = p.U; + + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.R = q.L; + if (p.R) p.R.U = p; + q.L = p; +} + +function RedBlackRotateRight(tree, node) { + var p = node, + q = node.L, + parent = p.U; + + if (parent) { + if (parent.L === p) parent.L = q; + else parent.R = q; + } else { + tree._ = q; + } + + q.U = parent; + p.U = q; + p.L = q.R; + if (p.L) p.L.U = p; + q.R = p; +} + +function RedBlackFirst(node) { + while (node.L) node = node.L; + return node; +} + +function createEdge(left, right, v0, v1) { + var edge = [null, null], + index = edges.push(edge) - 1; + edge.left = left; + edge.right = right; + if (v0) setEdgeEnd(edge, left, right, v0); + if (v1) setEdgeEnd(edge, right, left, v1); + cells[left.index].halfedges.push(index); + cells[right.index].halfedges.push(index); + return edge; +} + +function createBorderEdge(left, v0, v1) { + var edge = [v0, v1]; + edge.left = left; + return edge; +} + +function setEdgeEnd(edge, left, right, vertex) { + if (!edge[0] && !edge[1]) { + edge[0] = vertex; + edge.left = left; + edge.right = right; + } else if (edge.left === right) { + edge[1] = vertex; + } else { + edge[0] = vertex; + } +} + +// Liang–Barsky line clipping. +function clipEdge(edge, x0, y0, x1, y1) { + var a = edge[0], + b = edge[1], + ax = a[0], + ay = a[1], + bx = b[0], + by = b[1], + t0 = 0, + t1 = 1, + dx = bx - ax, + dy = by - ay, + r; + + r = x0 - ax; + if (!dx && r > 0) return; + r /= dx; + if (dx < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dx > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = x1 - ax; + if (!dx && r < 0) return; + r /= dx; + if (dx < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dx > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + r = y0 - ay; + if (!dy && r > 0) return; + r /= dy; + if (dy < 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } else if (dy > 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } + + r = y1 - ay; + if (!dy && r < 0) return; + r /= dy; + if (dy < 0) { + if (r > t1) return; + if (r > t0) t0 = r; + } else if (dy > 0) { + if (r < t0) return; + if (r < t1) t1 = r; + } + + if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check? + + if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy]; + if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy]; + return true; +} + +function connectEdge(edge, x0, y0, x1, y1) { + var v1 = edge[1]; + if (v1) return true; + + var v0 = edge[0], + left = edge.left, + right = edge.right, + lx = left[0], + ly = left[1], + rx = right[0], + ry = right[1], + fx = (lx + rx) / 2, + fy = (ly + ry) / 2, + fm, + fb; + + if (ry === ly) { + if (fx < x0 || fx >= x1) return; + if (lx > rx) { + if (!v0) v0 = [fx, y0]; + else if (v0[1] >= y1) return; + v1 = [fx, y1]; + } else { + if (!v0) v0 = [fx, y1]; + else if (v0[1] < y0) return; + v1 = [fx, y0]; + } + } else { + fm = (lx - rx) / (ry - ly); + fb = fy - fm * fx; + if (fm < -1 || fm > 1) { + if (lx > rx) { + if (!v0) v0 = [(y0 - fb) / fm, y0]; + else if (v0[1] >= y1) return; + v1 = [(y1 - fb) / fm, y1]; + } else { + if (!v0) v0 = [(y1 - fb) / fm, y1]; + else if (v0[1] < y0) return; + v1 = [(y0 - fb) / fm, y0]; + } + } else { + if (ly < ry) { + if (!v0) v0 = [x0, fm * x0 + fb]; + else if (v0[0] >= x1) return; + v1 = [x1, fm * x1 + fb]; + } else { + if (!v0) v0 = [x1, fm * x1 + fb]; + else if (v0[0] < x0) return; + v1 = [x0, fm * x0 + fb]; + } + } + } + + edge[0] = v0; + edge[1] = v1; + return true; +} + +function clipEdges(x0, y0, x1, y1) { + var i = edges.length, + edge; + + while (i--) { + if (!connectEdge(edge = edges[i], x0, y0, x1, y1) + || !clipEdge(edge, x0, y0, x1, y1) + || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon + || Math.abs(edge[0][1] - edge[1][1]) > epsilon)) { + delete edges[i]; + } + } +} + +function createCell(site) { + return cells[site.index] = { + site: site, + halfedges: [] + }; +} + +function cellHalfedgeAngle(cell, edge) { + var site = cell.site, + va = edge.left, + vb = edge.right; + if (site === vb) vb = va, va = site; + if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]); + if (site === va) va = edge[1], vb = edge[0]; + else va = edge[0], vb = edge[1]; + return Math.atan2(va[0] - vb[0], vb[1] - va[1]); +} + +function cellHalfedgeStart(cell, edge) { + return edge[+(edge.left !== cell.site)]; +} + +function cellHalfedgeEnd(cell, edge) { + return edge[+(edge.left === cell.site)]; +} + +function sortCellHalfedges() { + for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { + if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { + var index = new Array(m), + array = new Array(m); + for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]); + index.sort(function(i, j) { return array[j] - array[i]; }); + for (j = 0; j < m; ++j) array[j] = halfedges[index[j]]; + for (j = 0; j < m; ++j) halfedges[j] = array[j]; + } + } +} + +function clipCells(x0, y0, x1, y1) { + var nCells = cells.length, + iCell, + cell, + site, + iHalfedge, + halfedges, + nHalfedges, + start, + startX, + startY, + end, + endX, + endY, + cover = true; + + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + halfedges = cell.halfedges; + iHalfedge = halfedges.length; + + // Remove any dangling clipped edges. + while (iHalfedge--) { + if (!edges[halfedges[iHalfedge]]) { + halfedges.splice(iHalfedge, 1); + } + } + + // Insert any border edges as necessary. + iHalfedge = 0, nHalfedges = halfedges.length; + while (iHalfedge < nHalfedges) { + end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1]; + start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1]; + if (Math.abs(endX - startX) > epsilon || Math.abs(endY - startY) > epsilon) { + halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, + Math.abs(endX - x0) < epsilon && y1 - endY > epsilon ? [x0, Math.abs(startX - x0) < epsilon ? startY : y1] + : Math.abs(endY - y1) < epsilon && x1 - endX > epsilon ? [Math.abs(startY - y1) < epsilon ? startX : x1, y1] + : Math.abs(endX - x1) < epsilon && endY - y0 > epsilon ? [x1, Math.abs(startX - x1) < epsilon ? startY : y0] + : Math.abs(endY - y0) < epsilon && endX - x0 > epsilon ? [Math.abs(startY - y0) < epsilon ? startX : x0, y0] + : null)) - 1); + ++nHalfedges; + } + } + + if (nHalfedges) cover = false; + } + } + + // If there weren’t any edges, have the closest site cover the extent. + // It doesn’t matter which corner of the extent we measure! + if (cover) { + var dx, dy, d2, dc = Infinity; + + for (iCell = 0, cover = null; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + site = cell.site; + dx = site[0] - x0; + dy = site[1] - y0; + d2 = dx * dx + dy * dy; + if (d2 < dc) dc = d2, cover = cell; + } + } + + if (cover) { + var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0]; + cover.halfedges.push( + edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, + edges.push(createBorderEdge(site, v01, v11)) - 1, + edges.push(createBorderEdge(site, v11, v10)) - 1, + edges.push(createBorderEdge(site, v10, v00)) - 1 + ); + } + } + + // Lastly delete any cells with no edges; these were entirely clipped. + for (iCell = 0; iCell < nCells; ++iCell) { + if (cell = cells[iCell]) { + if (!cell.halfedges.length) { + delete cells[iCell]; + } + } + } +} + +var circlePool = []; + +var firstCircle; + +function Circle() { + RedBlackNode(this); + this.x = + this.y = + this.arc = + this.site = + this.cy = null; +} + +function attachCircle(arc) { + var lArc = arc.P, + rArc = arc.N; + + if (!lArc || !rArc) return; + + var lSite = lArc.site, + cSite = arc.site, + rSite = rArc.site; + + if (lSite === rSite) return; + + var bx = cSite[0], + by = cSite[1], + ax = lSite[0] - bx, + ay = lSite[1] - by, + cx = rSite[0] - bx, + cy = rSite[1] - by; + + var d = 2 * (ax * cy - ay * cx); + if (d >= -epsilon2) return; + + var ha = ax * ax + ay * ay, + hc = cx * cx + cy * cy, + x = (cy * ha - ay * hc) / d, + y = (ax * hc - cx * ha) / d; + + var circle = circlePool.pop() || new Circle; + circle.arc = arc; + circle.site = cSite; + circle.x = x + bx; + circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom + + arc.circle = circle; + + var before = null, + node = circles._; + + while (node) { + if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) { + if (node.L) node = node.L; + else { before = node.P; break; } + } else { + if (node.R) node = node.R; + else { before = node; break; } + } + } + + circles.insert(before, circle); + if (!before) firstCircle = circle; +} + +function detachCircle(arc) { + var circle = arc.circle; + if (circle) { + if (!circle.P) firstCircle = circle.N; + circles.remove(circle); + circlePool.push(circle); + RedBlackNode(circle); + arc.circle = null; + } +} + +var beachPool = []; + +function Beach() { + RedBlackNode(this); + this.edge = + this.site = + this.circle = null; +} + +function createBeach(site) { + var beach = beachPool.pop() || new Beach; + beach.site = site; + return beach; +} + +function detachBeach(beach) { + detachCircle(beach); + beaches.remove(beach); + beachPool.push(beach); + RedBlackNode(beach); +} + +function removeBeach(beach) { + var circle = beach.circle, + x = circle.x, + y = circle.cy, + vertex = [x, y], + previous = beach.P, + next = beach.N, + disappearing = [beach]; + + detachBeach(beach); + + var lArc = previous; + while (lArc.circle + && Math.abs(x - lArc.circle.x) < epsilon + && Math.abs(y - lArc.circle.cy) < epsilon) { + previous = lArc.P; + disappearing.unshift(lArc); + detachBeach(lArc); + lArc = previous; + } + + disappearing.unshift(lArc); + detachCircle(lArc); + + var rArc = next; + while (rArc.circle + && Math.abs(x - rArc.circle.x) < epsilon + && Math.abs(y - rArc.circle.cy) < epsilon) { + next = rArc.N; + disappearing.push(rArc); + detachBeach(rArc); + rArc = next; + } + + disappearing.push(rArc); + detachCircle(rArc); + + var nArcs = disappearing.length, + iArc; + for (iArc = 1; iArc < nArcs; ++iArc) { + rArc = disappearing[iArc]; + lArc = disappearing[iArc - 1]; + setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex); + } + + lArc = disappearing[0]; + rArc = disappearing[nArcs - 1]; + rArc.edge = createEdge(lArc.site, rArc.site, null, vertex); + + attachCircle(lArc); + attachCircle(rArc); +} + +function addBeach(site) { + var x = site[0], + directrix = site[1], + lArc, + rArc, + dxl, + dxr, + node = beaches._; + + while (node) { + dxl = leftBreakPoint(node, directrix) - x; + if (dxl > epsilon) node = node.L; else { + dxr = x - rightBreakPoint(node, directrix); + if (dxr > epsilon) { + if (!node.R) { + lArc = node; + break; + } + node = node.R; + } else { + if (dxl > -epsilon) { + lArc = node.P; + rArc = node; + } else if (dxr > -epsilon) { + lArc = node; + rArc = node.N; + } else { + lArc = rArc = node; + } + break; + } + } + } + + createCell(site); + var newArc = createBeach(site); + beaches.insert(lArc, newArc); + + if (!lArc && !rArc) return; + + if (lArc === rArc) { + detachCircle(lArc); + rArc = createBeach(lArc.site); + beaches.insert(newArc, rArc); + newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site); + attachCircle(lArc); + attachCircle(rArc); + return; + } + + if (!rArc) { // && lArc + newArc.edge = createEdge(lArc.site, newArc.site); + return; + } + + // else lArc !== rArc + detachCircle(lArc); + detachCircle(rArc); + + var lSite = lArc.site, + ax = lSite[0], + ay = lSite[1], + bx = site[0] - ax, + by = site[1] - ay, + rSite = rArc.site, + cx = rSite[0] - ax, + cy = rSite[1] - ay, + d = 2 * (bx * cy - by * cx), + hb = bx * bx + by * by, + hc = cx * cx + cy * cy, + vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay]; + + setEdgeEnd(rArc.edge, lSite, rSite, vertex); + newArc.edge = createEdge(lSite, site, null, vertex); + rArc.edge = createEdge(site, rSite, null, vertex); + attachCircle(lArc); + attachCircle(rArc); +} + +function leftBreakPoint(arc, directrix) { + var site = arc.site, + rfocx = site[0], + rfocy = site[1], + pby2 = rfocy - directrix; + + if (!pby2) return rfocx; + + var lArc = arc.P; + if (!lArc) return -Infinity; + + site = lArc.site; + var lfocx = site[0], + lfocy = site[1], + plby2 = lfocy - directrix; + + if (!plby2) return lfocx; + + var hl = lfocx - rfocx, + aby2 = 1 / pby2 - 1 / plby2, + b = hl / plby2; + + if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx; + + return (rfocx + lfocx) / 2; +} + +function rightBreakPoint(arc, directrix) { + var rArc = arc.N; + if (rArc) return leftBreakPoint(rArc, directrix); + var site = arc.site; + return site[1] === directrix ? site[0] : Infinity; +} + +var epsilon = 1e-6; +var epsilon2 = 1e-12; +var beaches; +var cells; +var circles; +var edges; + +function triangleArea(a, b, c) { + return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]); +} + +function lexicographic(a, b) { + return b[1] - a[1] + || b[0] - a[0]; +} + +function Diagram(sites, extent) { + var site = sites.sort(lexicographic).pop(), + x, + y, + circle; + + edges = []; + cells = new Array(sites.length); + beaches = new RedBlackTree; + circles = new RedBlackTree; + + while (true) { + circle = firstCircle; + if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { + if (site[0] !== x || site[1] !== y) { + addBeach(site); + x = site[0], y = site[1]; + } + site = sites.pop(); + } else if (circle) { + removeBeach(circle.arc); + } else { + break; + } + } + + sortCellHalfedges(); + + if (extent) { + var x0 = +extent[0][0], + y0 = +extent[0][1], + x1 = +extent[1][0], + y1 = +extent[1][1]; + clipEdges(x0, y0, x1, y1); + clipCells(x0, y0, x1, y1); + } + + this.edges = edges; + this.cells = cells; + + beaches = + circles = + edges = + cells = null; +} + +Diagram.prototype = { + constructor: Diagram, + + polygons: function() { + var edges = this.edges; + + return this.cells.map(function(cell) { + var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); }); + polygon.data = cell.site.data; + return polygon; + }); + }, + + triangles: function() { + var triangles = [], + edges = this.edges; + + this.cells.forEach(function(cell, i) { + if (!(m = (halfedges = cell.halfedges).length)) return; + var site = cell.site, + halfedges, + j = -1, + m, + s0, + e1 = edges[halfedges[m - 1]], + s1 = e1.left === site ? e1.right : e1.left; + + while (++j < m) { + s0 = s1; + e1 = edges[halfedges[j]]; + s1 = e1.left === site ? e1.right : e1.left; + if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { + triangles.push([site.data, s0.data, s1.data]); + } + } + }); + + return triangles; + }, + + links: function() { + return this.edges.filter(function(edge) { + return edge.right; + }).map(function(edge) { + return { + source: edge.left.data, + target: edge.right.data + }; + }); + }, + + find: function(x, y, radius) { + var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell; + + // Use the previously-found cell, or start with an arbitrary one. + while (!(cell = that.cells[i1])) if (++i1 >= n) return null; + var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy; + + // Traverse the half-edges to find a closer cell, if any. + do { + cell = that.cells[i0 = i1], i1 = null; + cell.halfedges.forEach(function(e) { + var edge = that.edges[e], v = edge.left; + if ((v === cell.site || !v) && !(v = edge.right)) return; + var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy; + if (v2 < d2) d2 = v2, i1 = v.index; + }); + } while (i1 !== null); + + that._found = i0; + + return radius == null || d2 <= radius * radius ? cell.site : null; + } +}; + +var voronoi = function() { + var x$$1 = x, + y$$1 = y, + extent = null; + + function voronoi(data) { + return new Diagram(data.map(function(d, i) { + var s = [Math.round(x$$1(d, i, data) / epsilon) * epsilon, Math.round(y$$1(d, i, data) / epsilon) * epsilon]; + s.index = i; + s.data = d; + return s; + }), extent); + } + + voronoi.polygons = function(data) { + return voronoi(data).polygons(); + }; + + voronoi.links = function(data) { + return voronoi(data).links(); + }; + + voronoi.triangles = function(data) { + return voronoi(data).triangles(); + }; + + voronoi.x = function(_) { + return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant(+_), voronoi) : x$$1; + }; + + voronoi.y = function(_) { + return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant(+_), voronoi) : y$$1; + }; + + voronoi.extent = function(_) { + return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]]; + }; + + voronoi.size = function(_) { + return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]]; + }; + + return voronoi; +}; + +exports.voronoi = voronoi; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{}],53:[function(require,module,exports){ +// https://d3js.org/d3-zoom/ Version 1.7.1. Copyright 2017 Mike Bostock. +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3-dispatch'), require('d3-drag'), require('d3-interpolate'), require('d3-selection'), require('d3-transition')) : + typeof define === 'function' && define.amd ? define(['exports', 'd3-dispatch', 'd3-drag', 'd3-interpolate', 'd3-selection', 'd3-transition'], factory) : + (factory((global.d3 = global.d3 || {}),global.d3,global.d3,global.d3,global.d3,global.d3)); +}(this, (function (exports,d3Dispatch,d3Drag,d3Interpolate,d3Selection,d3Transition) { 'use strict'; + +var constant = function(x) { + return function() { + return x; + }; +}; + +function ZoomEvent(target, type, transform) { + this.target = target; + this.type = type; + this.transform = transform; +} + +function Transform(k, x, y) { + this.k = k; + this.x = x; + this.y = y; +} + +Transform.prototype = { + constructor: Transform, + scale: function(k) { + return k === 1 ? this : new Transform(this.k * k, this.x, this.y); + }, + translate: function(x, y) { + return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y); + }, + apply: function(point) { + return [point[0] * this.k + this.x, point[1] * this.k + this.y]; + }, + applyX: function(x) { + return x * this.k + this.x; + }, + applyY: function(y) { + return y * this.k + this.y; + }, + invert: function(location) { + return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k]; + }, + invertX: function(x) { + return (x - this.x) / this.k; + }, + invertY: function(y) { + return (y - this.y) / this.k; + }, + rescaleX: function(x) { + return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x)); + }, + rescaleY: function(y) { + return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y)); + }, + toString: function() { + return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")"; + } +}; + +var identity = new Transform(1, 0, 0); + +transform.prototype = Transform.prototype; + +function transform(node) { + return node.__zoom || identity; +} + +function nopropagation() { + d3Selection.event.stopImmediatePropagation(); +} + +var noevent = function() { + d3Selection.event.preventDefault(); + d3Selection.event.stopImmediatePropagation(); +}; + +// Ignore right-click, since that should open the context menu. +function defaultFilter() { + return !d3Selection.event.button; +} + +function defaultExtent() { + var e = this, w, h; + if (e instanceof SVGElement) { + e = e.ownerSVGElement || e; + w = e.width.baseVal.value; + h = e.height.baseVal.value; + } else { + w = e.clientWidth; + h = e.clientHeight; + } + return [[0, 0], [w, h]]; +} + +function defaultTransform() { + return this.__zoom || identity; +} + +function defaultWheelDelta() { + return -d3Selection.event.deltaY * (d3Selection.event.deltaMode ? 120 : 1) / 500; +} + +function defaultTouchable() { + return "ontouchstart" in this; +} + +function defaultConstrain(transform$$1, extent, translateExtent) { + var dx0 = transform$$1.invertX(extent[0][0]) - translateExtent[0][0], + dx1 = transform$$1.invertX(extent[1][0]) - translateExtent[1][0], + dy0 = transform$$1.invertY(extent[0][1]) - translateExtent[0][1], + dy1 = transform$$1.invertY(extent[1][1]) - translateExtent[1][1]; + return transform$$1.translate( + dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), + dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1) + ); +} + +var zoom = function() { + var filter = defaultFilter, + extent = defaultExtent, + constrain = defaultConstrain, + wheelDelta = defaultWheelDelta, + touchable = defaultTouchable, + scaleExtent = [0, Infinity], + translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], + duration = 250, + interpolate = d3Interpolate.interpolateZoom, + gestures = [], + listeners = d3Dispatch.dispatch("start", "zoom", "end"), + touchstarting, + touchending, + touchDelay = 500, + wheelDelay = 150, + clickDistance2 = 0; + + function zoom(selection) { + selection + .property("__zoom", defaultTransform) + .on("wheel.zoom", wheeled) + .on("mousedown.zoom", mousedowned) + .on("dblclick.zoom", dblclicked) + .filter(touchable) + .on("touchstart.zoom", touchstarted) + .on("touchmove.zoom", touchmoved) + .on("touchend.zoom touchcancel.zoom", touchended) + .style("touch-action", "none") + .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)"); + } + + zoom.transform = function(collection, transform$$1) { + var selection = collection.selection ? collection.selection() : collection; + selection.property("__zoom", defaultTransform); + if (collection !== selection) { + schedule(collection, transform$$1); + } else { + selection.interrupt().each(function() { + gesture(this, arguments) + .start() + .zoom(null, typeof transform$$1 === "function" ? transform$$1.apply(this, arguments) : transform$$1) + .end(); + }); + } + }; + + zoom.scaleBy = function(selection, k) { + zoom.scaleTo(selection, function() { + var k0 = this.__zoom.k, + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return k0 * k1; + }); + }; + + zoom.scaleTo = function(selection, k) { + zoom.transform(selection, function() { + var e = extent.apply(this, arguments), + t0 = this.__zoom, + p0 = centroid(e), + p1 = t0.invert(p0), + k1 = typeof k === "function" ? k.apply(this, arguments) : k; + return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent); + }); + }; + + zoom.translateBy = function(selection, x, y) { + zoom.transform(selection, function() { + return constrain(this.__zoom.translate( + typeof x === "function" ? x.apply(this, arguments) : x, + typeof y === "function" ? y.apply(this, arguments) : y + ), extent.apply(this, arguments), translateExtent); + }); + }; + + zoom.translateTo = function(selection, x, y) { + zoom.transform(selection, function() { + var e = extent.apply(this, arguments), + t = this.__zoom, + p = centroid(e); + return constrain(identity.translate(p[0], p[1]).scale(t.k).translate( + typeof x === "function" ? -x.apply(this, arguments) : -x, + typeof y === "function" ? -y.apply(this, arguments) : -y + ), e, translateExtent); + }); + }; + + function scale(transform$$1, k) { + k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k)); + return k === transform$$1.k ? transform$$1 : new Transform(k, transform$$1.x, transform$$1.y); + } + + function translate(transform$$1, p0, p1) { + var x = p0[0] - p1[0] * transform$$1.k, y = p0[1] - p1[1] * transform$$1.k; + return x === transform$$1.x && y === transform$$1.y ? transform$$1 : new Transform(transform$$1.k, x, y); + } + + function centroid(extent) { + return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2]; + } + + function schedule(transition, transform$$1, center) { + transition + .on("start.zoom", function() { gesture(this, arguments).start(); }) + .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); }) + .tween("zoom", function() { + var that = this, + args = arguments, + g = gesture(that, args), + e = extent.apply(that, args), + p = center || centroid(e), + w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), + a = that.__zoom, + b = typeof transform$$1 === "function" ? transform$$1.apply(that, args) : transform$$1, + i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k)); + return function(t) { + if (t === 1) t = b; // Avoid rounding error on end. + else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); } + g.zoom(null, t); + }; + }); + } + + function gesture(that, args) { + for (var i = 0, n = gestures.length, g; i < n; ++i) { + if ((g = gestures[i]).that === that) { + return g; + } + } + return new Gesture(that, args); + } + + function Gesture(that, args) { + this.that = that; + this.args = args; + this.index = -1; + this.active = 0; + this.extent = extent.apply(that, args); + } + + Gesture.prototype = { + start: function() { + if (++this.active === 1) { + this.index = gestures.push(this) - 1; + this.emit("start"); + } + return this; + }, + zoom: function(key, transform$$1) { + if (this.mouse && key !== "mouse") this.mouse[1] = transform$$1.invert(this.mouse[0]); + if (this.touch0 && key !== "touch") this.touch0[1] = transform$$1.invert(this.touch0[0]); + if (this.touch1 && key !== "touch") this.touch1[1] = transform$$1.invert(this.touch1[0]); + this.that.__zoom = transform$$1; + this.emit("zoom"); + return this; + }, + end: function() { + if (--this.active === 0) { + gestures.splice(this.index, 1); + this.index = -1; + this.emit("end"); + } + return this; + }, + emit: function(type) { + d3Selection.customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]); + } + }; + + function wheeled() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + t = this.__zoom, + k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), + p = d3Selection.mouse(this); + + // If the mouse is in the same location as before, reuse it. + // If there were recent wheel events, reset the wheel idle timeout. + if (g.wheel) { + if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) { + g.mouse[1] = t.invert(g.mouse[0] = p); + } + clearTimeout(g.wheel); + } + + // If this wheel event won’t trigger a transform change, ignore it. + else if (t.k === k) return; + + // Otherwise, capture the mouse point and location at the start. + else { + g.mouse = [p, t.invert(p)]; + d3Transition.interrupt(this); + g.start(); + } + + noevent(); + g.wheel = setTimeout(wheelidled, wheelDelay); + g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent)); + + function wheelidled() { + g.wheel = null; + g.end(); + } + } + + function mousedowned() { + if (touchending || !filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + v = d3Selection.select(d3Selection.event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true), + p = d3Selection.mouse(this), + x0 = d3Selection.event.clientX, + y0 = d3Selection.event.clientY; + + d3Drag.dragDisable(d3Selection.event.view); + nopropagation(); + g.mouse = [p, this.__zoom.invert(p)]; + d3Transition.interrupt(this); + g.start(); + + function mousemoved() { + noevent(); + if (!g.moved) { + var dx = d3Selection.event.clientX - x0, dy = d3Selection.event.clientY - y0; + g.moved = dx * dx + dy * dy > clickDistance2; + } + g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = d3Selection.mouse(g.that), g.mouse[1]), g.extent, translateExtent)); + } + + function mouseupped() { + v.on("mousemove.zoom mouseup.zoom", null); + d3Drag.dragEnable(d3Selection.event.view, g.moved); + noevent(); + g.end(); + } + } + + function dblclicked() { + if (!filter.apply(this, arguments)) return; + var t0 = this.__zoom, + p0 = d3Selection.mouse(this), + p1 = t0.invert(p0), + k1 = t0.k * (d3Selection.event.shiftKey ? 0.5 : 2), + t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments), translateExtent); + + noevent(); + if (duration > 0) d3Selection.select(this).transition().duration(duration).call(schedule, t1, p0); + else d3Selection.select(this).call(zoom.transform, t1); + } + + function touchstarted() { + if (!filter.apply(this, arguments)) return; + var g = gesture(this, arguments), + touches = d3Selection.event.changedTouches, + started, + n = touches.length, i, t, p; + + nopropagation(); + for (i = 0; i < n; ++i) { + t = touches[i], p = d3Selection.touch(this, touches, t.identifier); + p = [p, this.__zoom.invert(p), t.identifier]; + if (!g.touch0) g.touch0 = p, started = true; + else if (!g.touch1) g.touch1 = p; + } + + // If this is a dbltap, reroute to the (optional) dblclick.zoom handler. + if (touchstarting) { + touchstarting = clearTimeout(touchstarting); + if (!g.touch1) { + g.end(); + p = d3Selection.select(this).on("dblclick.zoom"); + if (p) p.apply(this, arguments); + return; + } + } + + if (started) { + touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay); + d3Transition.interrupt(this); + g.start(); + } + } + + function touchmoved() { + var g = gesture(this, arguments), + touches = d3Selection.event.changedTouches, + n = touches.length, i, t, p, l; + + noevent(); + if (touchstarting) touchstarting = clearTimeout(touchstarting); + for (i = 0; i < n; ++i) { + t = touches[i], p = d3Selection.touch(this, touches, t.identifier); + if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p; + else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p; + } + t = g.that.__zoom; + if (g.touch1) { + var p0 = g.touch0[0], l0 = g.touch0[1], + p1 = g.touch1[0], l1 = g.touch1[1], + dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, + dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl; + t = scale(t, Math.sqrt(dp / dl)); + p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2]; + l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2]; + } + else if (g.touch0) p = g.touch0[0], l = g.touch0[1]; + else return; + g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent)); + } + + function touchended() { + var g = gesture(this, arguments), + touches = d3Selection.event.changedTouches, + n = touches.length, i, t; + + nopropagation(); + if (touchending) clearTimeout(touchending); + touchending = setTimeout(function() { touchending = null; }, touchDelay); + for (i = 0; i < n; ++i) { + t = touches[i]; + if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0; + else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1; + } + if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1; + if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]); + else g.end(); + } + + zoom.wheelDelta = function(_) { + return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant(+_), zoom) : wheelDelta; + }; + + zoom.filter = function(_) { + return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), zoom) : filter; + }; + + zoom.touchable = function(_) { + return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), zoom) : touchable; + }; + + zoom.extent = function(_) { + return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent; + }; + + zoom.scaleExtent = function(_) { + return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]]; + }; + + zoom.translateExtent = function(_) { + return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]]; + }; + + zoom.constrain = function(_) { + return arguments.length ? (constrain = _, zoom) : constrain; + }; + + zoom.duration = function(_) { + return arguments.length ? (duration = +_, zoom) : duration; + }; + + zoom.interpolate = function(_) { + return arguments.length ? (interpolate = _, zoom) : interpolate; + }; + + zoom.on = function() { + var value = listeners.on.apply(listeners, arguments); + return value === listeners ? zoom : value; + }; + + zoom.clickDistance = function(_) { + return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2); + }; + + return zoom; +}; + +exports.zoom = zoom; +exports.zoomTransform = transform; +exports.zoomIdentity = identity; + +Object.defineProperty(exports, '__esModule', { value: true }); + +}))); + +},{"d3-dispatch":29,"d3-drag":30,"d3-interpolate":37,"d3-selection":45,"d3-transition":51}],54:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, '__esModule', { value: true }); + +var d3Array = require('d3-array'); +var d3Axis = require('d3-axis'); +var d3Brush = require('d3-brush'); +var d3Chord = require('d3-chord'); +var d3Collection = require('d3-collection'); +var d3Color = require('d3-color'); +var d3Dispatch = require('d3-dispatch'); +var d3Drag = require('d3-drag'); +var d3Dsv = require('d3-dsv'); +var d3Ease = require('d3-ease'); +var d3Force = require('d3-force'); +var d3Format = require('d3-format'); +var d3Geo = require('d3-geo'); +var d3Hierarchy = require('d3-hierarchy'); +var d3Interpolate = require('d3-interpolate'); +var d3Path = require('d3-path'); +var d3Polygon = require('d3-polygon'); +var d3Quadtree = require('d3-quadtree'); +var d3Queue = require('d3-queue'); +var d3Random = require('d3-random'); +var d3Request = require('d3-request'); +var d3Scale = require('d3-scale'); +var d3Selection = require('d3-selection'); +var d3Shape = require('d3-shape'); +var d3Time = require('d3-time'); +var d3TimeFormat = require('d3-time-format'); +var d3Timer = require('d3-timer'); +var d3Transition = require('d3-transition'); +var d3Voronoi = require('d3-voronoi'); +var d3Zoom = require('d3-zoom'); + +var version = "4.13.0"; + +exports.version = version; +Object.keys(d3Array).forEach(function (key) { exports[key] = d3Array[key]; }); +Object.keys(d3Axis).forEach(function (key) { exports[key] = d3Axis[key]; }); +Object.keys(d3Brush).forEach(function (key) { exports[key] = d3Brush[key]; }); +Object.keys(d3Chord).forEach(function (key) { exports[key] = d3Chord[key]; }); +Object.keys(d3Collection).forEach(function (key) { exports[key] = d3Collection[key]; }); +Object.keys(d3Color).forEach(function (key) { exports[key] = d3Color[key]; }); +Object.keys(d3Dispatch).forEach(function (key) { exports[key] = d3Dispatch[key]; }); +Object.keys(d3Drag).forEach(function (key) { exports[key] = d3Drag[key]; }); +Object.keys(d3Dsv).forEach(function (key) { exports[key] = d3Dsv[key]; }); +Object.keys(d3Ease).forEach(function (key) { exports[key] = d3Ease[key]; }); +Object.keys(d3Force).forEach(function (key) { exports[key] = d3Force[key]; }); +Object.keys(d3Format).forEach(function (key) { exports[key] = d3Format[key]; }); +Object.keys(d3Geo).forEach(function (key) { exports[key] = d3Geo[key]; }); +Object.keys(d3Hierarchy).forEach(function (key) { exports[key] = d3Hierarchy[key]; }); +Object.keys(d3Interpolate).forEach(function (key) { exports[key] = d3Interpolate[key]; }); +Object.keys(d3Path).forEach(function (key) { exports[key] = d3Path[key]; }); +Object.keys(d3Polygon).forEach(function (key) { exports[key] = d3Polygon[key]; }); +Object.keys(d3Quadtree).forEach(function (key) { exports[key] = d3Quadtree[key]; }); +Object.keys(d3Queue).forEach(function (key) { exports[key] = d3Queue[key]; }); +Object.keys(d3Random).forEach(function (key) { exports[key] = d3Random[key]; }); +Object.keys(d3Request).forEach(function (key) { exports[key] = d3Request[key]; }); +Object.keys(d3Scale).forEach(function (key) { exports[key] = d3Scale[key]; }); +Object.keys(d3Selection).forEach(function (key) { exports[key] = d3Selection[key]; }); +Object.keys(d3Shape).forEach(function (key) { exports[key] = d3Shape[key]; }); +Object.keys(d3Time).forEach(function (key) { exports[key] = d3Time[key]; }); +Object.keys(d3TimeFormat).forEach(function (key) { exports[key] = d3TimeFormat[key]; }); +Object.keys(d3Timer).forEach(function (key) { exports[key] = d3Timer[key]; }); +Object.keys(d3Transition).forEach(function (key) { exports[key] = d3Transition[key]; }); +Object.keys(d3Voronoi).forEach(function (key) { exports[key] = d3Voronoi[key]; }); +Object.keys(d3Zoom).forEach(function (key) { exports[key] = d3Zoom[key]; }); +Object.defineProperty(exports, "event", {get: function() { return d3Selection.event; }}); + +},{"d3-array":23,"d3-axis":24,"d3-brush":25,"d3-chord":26,"d3-collection":27,"d3-color":28,"d3-dispatch":29,"d3-drag":30,"d3-dsv":31,"d3-ease":32,"d3-force":33,"d3-format":34,"d3-geo":35,"d3-hierarchy":36,"d3-interpolate":37,"d3-path":38,"d3-polygon":39,"d3-quadtree":40,"d3-queue":41,"d3-random":42,"d3-request":43,"d3-scale":44,"d3-selection":45,"d3-shape":46,"d3-time":48,"d3-time-format":47,"d3-timer":49,"d3-transition":51,"d3-voronoi":52,"d3-zoom":53}],55:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); + err.context = er; + throw err; + } + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + args = Array.prototype.slice.call(arguments, 1); + handler.apply(this, args); + } + } else if (isObject(handler)) { + args = Array.prototype.slice.call(arguments, 1); + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.prototype.listenerCount = function(type) { + if (this._events) { + var evlistener = this._events[type]; + + if (isFunction(evlistener)) + return 1; + else if (evlistener) + return evlistener.length; + } + return 0; +}; + +EventEmitter.listenerCount = function(emitter, type) { + return emitter.listenerCount(type); +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],56:[function(require,module,exports){ +var http = require('http'); + +var https = module.exports; + +for (var key in http) { + if (http.hasOwnProperty(key)) https[key] = http[key]; +}; + +https.request = function (params, cb) { + if (!params) params = {}; + params.scheme = 'https'; + params.protocol = 'https:'; + return http.request.call(this, params, cb); +} + +},{"http":78}],57:[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],58:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],59:[function(require,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],60:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + +},{}],61:[function(require,module,exports){ +!function(global, factory) { + 'object' == typeof exports && 'undefined' != typeof module ? factory(exports) : 'function' == typeof define && define.amd ? define([ 'exports' ], factory) : factory(global.preact = global.preact || {}); +}(this, function(exports) { + function VNode(nodeName, attributes, children) { + this.nodeName = nodeName; + this.attributes = attributes; + this.children = children; + this.key = attributes && attributes.key; + } + function h(nodeName, attributes) { + var lastSimple, child, simple, i, children = []; + for (i = arguments.length; i-- > 2; ) stack.push(arguments[i]); + if (attributes && attributes.children) { + if (!stack.length) stack.push(attributes.children); + delete attributes.children; + } + while (stack.length) if ((child = stack.pop()) instanceof Array) for (i = child.length; i--; ) stack.push(child[i]); else if (null != child && child !== !1) { + if ('number' == typeof child || child === !0) child = String(child); + simple = 'string' == typeof child; + if (simple && lastSimple) children[children.length - 1] += child; else { + children.push(child); + lastSimple = simple; + } + } + var p = new VNode(nodeName, attributes || void 0, children); + if (options.vnode) options.vnode(p); + return p; + } + function extend(obj, props) { + if (props) for (var i in props) obj[i] = props[i]; + return obj; + } + function clone(obj) { + return extend({}, obj); + } + function delve(obj, key) { + for (var p = key.split('.'), i = 0; i < p.length && obj; i++) obj = obj[p[i]]; + return obj; + } + function isFunction(obj) { + return 'function' == typeof obj; + } + function isString(obj) { + return 'string' == typeof obj; + } + function hashToClassName(c) { + var str = ''; + for (var prop in c) if (c[prop]) { + if (str) str += ' '; + str += prop; + } + return str; + } + function cloneElement(vnode, props) { + return h(vnode.nodeName, extend(clone(vnode.attributes), props), arguments.length > 2 ? [].slice.call(arguments, 2) : vnode.children); + } + function createLinkedState(component, key, eventPath) { + var path = key.split('.'); + return function(e) { + var t = e && e.target || this, state = {}, obj = state, v = isString(eventPath) ? delve(e, eventPath) : t.nodeName ? t.type.match(/^che|rad/) ? t.checked : t.value : e, i = 0; + for (;i < path.length - 1; i++) obj = obj[path[i]] || (obj[path[i]] = !i && component.state[path[i]] || {}); + obj[path[i]] = v; + component.setState(state); + }; + } + function enqueueRender(component) { + if (!component._dirty && (component._dirty = !0) && 1 == items.push(component)) (options.debounceRendering || defer)(rerender); + } + function rerender() { + var p, list = items; + items = []; + while (p = list.pop()) if (p._dirty) renderComponent(p); + } + function isFunctionalComponent(vnode) { + var nodeName = vnode && vnode.nodeName; + return nodeName && isFunction(nodeName) && !(nodeName.prototype && nodeName.prototype.render); + } + function buildFunctionalComponent(vnode, context) { + return vnode.nodeName(getNodeProps(vnode), context || EMPTY); + } + function isSameNodeType(node, vnode) { + if (isString(vnode)) return node instanceof Text; + if (isString(vnode.nodeName)) return isNamedNode(node, vnode.nodeName); + if (isFunction(vnode.nodeName)) return node._componentConstructor === vnode.nodeName || isFunctionalComponent(vnode); else ; + } + function isNamedNode(node, nodeName) { + return node.normalizedNodeName === nodeName || toLowerCase(node.nodeName) === toLowerCase(nodeName); + } + function getNodeProps(vnode) { + var props = clone(vnode.attributes); + props.children = vnode.children; + var defaultProps = vnode.nodeName.defaultProps; + if (defaultProps) for (var i in defaultProps) if (void 0 === props[i]) props[i] = defaultProps[i]; + return props; + } + function removeNode(node) { + var p = node.parentNode; + if (p) p.removeChild(node); + } + function setAccessor(node, name, old, value, isSvg) { + if ('className' === name) name = 'class'; + if ('class' === name && value && 'object' == typeof value) value = hashToClassName(value); + if ('key' === name) ; else if ('class' === name && !isSvg) node.className = value || ''; else if ('style' === name) { + if (!value || isString(value) || isString(old)) node.style.cssText = value || ''; + if (value && 'object' == typeof value) { + if (!isString(old)) for (var i in old) if (!(i in value)) node.style[i] = ''; + for (var i in value) node.style[i] = 'number' == typeof value[i] && !NON_DIMENSION_PROPS[i] ? value[i] + 'px' : value[i]; + } + } else if ('dangerouslySetInnerHTML' === name) { + if (value) node.innerHTML = value.__html; + } else if ('o' == name[0] && 'n' == name[1]) { + var l = node._listeners || (node._listeners = {}); + name = toLowerCase(name.substring(2)); + if (value) { + if (!l[name]) node.addEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]); + } else if (l[name]) node.removeEventListener(name, eventProxy, !!NON_BUBBLING_EVENTS[name]); + l[name] = value; + } else if ('list' !== name && 'type' !== name && !isSvg && name in node) { + setProperty(node, name, null == value ? '' : value); + if (null == value || value === !1) node.removeAttribute(name); + } else { + var ns = isSvg && name.match(/^xlink\:?(.+)/); + if (null == value || value === !1) if (ns) node.removeAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1])); else node.removeAttribute(name); else if ('object' != typeof value && !isFunction(value)) if (ns) node.setAttributeNS('http://www.w3.org/1999/xlink', toLowerCase(ns[1]), value); else node.setAttribute(name, value); + } + } + function setProperty(node, name, value) { + try { + node[name] = value; + } catch (e) {} + } + function eventProxy(e) { + return this._listeners[e.type](options.event && options.event(e) || e); + } + function collectNode(node) { + removeNode(node); + if (node instanceof Element) { + node._component = node._componentConstructor = null; + var _name = node.normalizedNodeName || toLowerCase(node.nodeName); + (nodes[_name] || (nodes[_name] = [])).push(node); + } + } + function createNode(nodeName, isSvg) { + var name = toLowerCase(nodeName), node = nodes[name] && nodes[name].pop() || (isSvg ? document.createElementNS('http://www.w3.org/2000/svg', nodeName) : document.createElement(nodeName)); + node.normalizedNodeName = name; + return node; + } + function flushMounts() { + var c; + while (c = mounts.pop()) { + if (options.afterMount) options.afterMount(c); + if (c.componentDidMount) c.componentDidMount(); + } + } + function diff(dom, vnode, context, mountAll, parent, componentRoot) { + if (!diffLevel++) isSvgMode = parent instanceof SVGElement; + var ret = idiff(dom, vnode, context, mountAll); + if (parent && ret.parentNode !== parent) parent.appendChild(ret); + if (!--diffLevel && !componentRoot) flushMounts(); + return ret; + } + function idiff(dom, vnode, context, mountAll) { + var originalAttributes = vnode && vnode.attributes; + while (isFunctionalComponent(vnode)) vnode = buildFunctionalComponent(vnode, context); + if (null == vnode) vnode = ''; + if (isString(vnode)) { + if (dom) { + if (dom instanceof Text && dom.parentNode) { + if (dom.nodeValue != vnode) dom.nodeValue = vnode; + return dom; + } + recollectNodeTree(dom); + } + return document.createTextNode(vnode); + } + if (isFunction(vnode.nodeName)) return buildComponentFromVNode(dom, vnode, context, mountAll); + var out = dom, nodeName = vnode.nodeName, prevSvgMode = isSvgMode, vchildren = vnode.children; + if (!isString(nodeName)) nodeName = String(nodeName); + isSvgMode = 'svg' === nodeName ? !0 : 'foreignObject' === nodeName ? !1 : isSvgMode; + if (!dom) out = createNode(nodeName, isSvgMode); else if (!isNamedNode(dom, nodeName)) { + out = createNode(nodeName, isSvgMode); + while (dom.firstChild) out.appendChild(dom.firstChild); + recollectNodeTree(dom); + } + if (vchildren && 1 === vchildren.length && 'string' == typeof vchildren[0] && 1 === out.childNodes.length && out.firstChild instanceof Text) { + if (out.firstChild.nodeValue != vchildren[0]) out.firstChild.nodeValue = vchildren[0]; + } else if (vchildren && vchildren.length || out.firstChild) innerDiffNode(out, vchildren, context, mountAll); + var props = out[ATTR_KEY]; + if (!props) { + out[ATTR_KEY] = props = {}; + for (var a = out.attributes, i = a.length; i--; ) props[a[i].name] = a[i].value; + } + diffAttributes(out, vnode.attributes, props); + if (originalAttributes && 'function' == typeof originalAttributes.ref) (props.ref = originalAttributes.ref)(out); + isSvgMode = prevSvgMode; + return out; + } + function innerDiffNode(dom, vchildren, context, mountAll) { + var j, c, vchild, child, originalChildren = dom.childNodes, children = [], keyed = {}, keyedLen = 0, min = 0, len = originalChildren.length, childrenLen = 0, vlen = vchildren && vchildren.length; + if (len) for (var i = 0; i < len; i++) { + var _child = originalChildren[i], key = vlen ? (c = _child._component) ? c.__key : (c = _child[ATTR_KEY]) ? c.key : null : null; + if (key || 0 === key) { + keyedLen++; + keyed[key] = _child; + } else children[childrenLen++] = _child; + } + if (vlen) for (var i = 0; i < vlen; i++) { + vchild = vchildren[i]; + child = null; + var key = vchild.key; + if (null != key) { + if (keyedLen && key in keyed) { + child = keyed[key]; + keyed[key] = void 0; + keyedLen--; + } + } else if (!child && min < childrenLen) { + for (j = min; j < childrenLen; j++) { + c = children[j]; + if (c && isSameNodeType(c, vchild)) { + child = c; + children[j] = void 0; + if (j === childrenLen - 1) childrenLen--; + if (j === min) min++; + break; + } + } + if (!child && min < childrenLen && isFunction(vchild.nodeName) && mountAll) { + child = children[min]; + children[min++] = void 0; + } + } + child = idiff(child, vchild, context, mountAll); + if (child && child !== dom && child !== originalChildren[i]) dom.insertBefore(child, originalChildren[i] || null); + } + if (keyedLen) for (var i in keyed) if (keyed[i]) recollectNodeTree(keyed[i]); + if (min < childrenLen) removeOrphanedChildren(children); + } + function removeOrphanedChildren(children, unmountOnly) { + for (var i = children.length; i--; ) if (children[i]) recollectNodeTree(children[i], unmountOnly); + } + function recollectNodeTree(node, unmountOnly) { + var component = node._component; + if (component) unmountComponent(component, !unmountOnly); else { + if (node[ATTR_KEY] && node[ATTR_KEY].ref) node[ATTR_KEY].ref(null); + if (!unmountOnly) collectNode(node); + if (node.childNodes && node.childNodes.length) removeOrphanedChildren(node.childNodes, unmountOnly); + } + } + function diffAttributes(dom, attrs, old) { + for (var _name in old) if (!(attrs && _name in attrs) && null != old[_name]) setAccessor(dom, _name, old[_name], old[_name] = void 0, isSvgMode); + if (attrs) for (var _name2 in attrs) if (!('children' === _name2 || 'innerHTML' === _name2 || _name2 in old && attrs[_name2] === ('value' === _name2 || 'checked' === _name2 ? dom[_name2] : old[_name2]))) setAccessor(dom, _name2, old[_name2], old[_name2] = attrs[_name2], isSvgMode); + } + function collectComponent(component) { + var name = component.constructor.name, list = components[name]; + if (list) list.push(component); else components[name] = [ component ]; + } + function createComponent(Ctor, props, context) { + var inst = new Ctor(props, context), list = components[Ctor.name]; + Component.call(inst, props, context); + if (list) for (var i = list.length; i--; ) if (list[i].constructor === Ctor) { + inst.nextBase = list[i].nextBase; + list.splice(i, 1); + break; + } + return inst; + } + function setComponentProps(component, props, opts, context, mountAll) { + if (!component._disable) { + component._disable = !0; + if (component.__ref = props.ref) delete props.ref; + if (component.__key = props.key) delete props.key; + if (!component.base || mountAll) { + if (component.componentWillMount) component.componentWillMount(); + } else if (component.componentWillReceiveProps) component.componentWillReceiveProps(props, context); + if (context && context !== component.context) { + if (!component.prevContext) component.prevContext = component.context; + component.context = context; + } + if (!component.prevProps) component.prevProps = component.props; + component.props = props; + component._disable = !1; + if (0 !== opts) if (1 === opts || options.syncComponentUpdates !== !1 || !component.base) renderComponent(component, 1, mountAll); else enqueueRender(component); + if (component.__ref) component.__ref(component); + } + } + function renderComponent(component, opts, mountAll, isChild) { + if (!component._disable) { + var skip, rendered, inst, cbase, props = component.props, state = component.state, context = component.context, previousProps = component.prevProps || props, previousState = component.prevState || state, previousContext = component.prevContext || context, isUpdate = component.base, nextBase = component.nextBase, initialBase = isUpdate || nextBase, initialChildComponent = component._component; + if (isUpdate) { + component.props = previousProps; + component.state = previousState; + component.context = previousContext; + if (2 !== opts && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === !1) skip = !0; else if (component.componentWillUpdate) component.componentWillUpdate(props, state, context); + component.props = props; + component.state = state; + component.context = context; + } + component.prevProps = component.prevState = component.prevContext = component.nextBase = null; + component._dirty = !1; + if (!skip) { + if (component.render) rendered = component.render(props, state, context); + if (component.getChildContext) context = extend(clone(context), component.getChildContext()); + while (isFunctionalComponent(rendered)) rendered = buildFunctionalComponent(rendered, context); + var toUnmount, base, childComponent = rendered && rendered.nodeName; + if (isFunction(childComponent)) { + inst = initialChildComponent; + var childProps = getNodeProps(rendered); + if (inst && inst.constructor === childComponent) setComponentProps(inst, childProps, 1, context); else { + toUnmount = inst; + inst = createComponent(childComponent, childProps, context); + inst.nextBase = inst.nextBase || nextBase; + inst._parentComponent = component; + component._component = inst; + setComponentProps(inst, childProps, 0, context); + renderComponent(inst, 1, mountAll, !0); + } + base = inst.base; + } else { + cbase = initialBase; + toUnmount = initialChildComponent; + if (toUnmount) cbase = component._component = null; + if (initialBase || 1 === opts) { + if (cbase) cbase._component = null; + base = diff(cbase, rendered, context, mountAll || !isUpdate, initialBase && initialBase.parentNode, !0); + } + } + if (initialBase && base !== initialBase && inst !== initialChildComponent) { + var baseParent = initialBase.parentNode; + if (baseParent && base !== baseParent) { + baseParent.replaceChild(base, initialBase); + if (!toUnmount) { + initialBase._component = null; + recollectNodeTree(initialBase); + } + } + } + if (toUnmount) unmountComponent(toUnmount, base !== initialBase); + component.base = base; + if (base && !isChild) { + var componentRef = component, t = component; + while (t = t._parentComponent) (componentRef = t).base = base; + base._component = componentRef; + base._componentConstructor = componentRef.constructor; + } + } + if (!isUpdate || mountAll) mounts.unshift(component); else if (!skip) { + if (component.componentDidUpdate) component.componentDidUpdate(previousProps, previousState, previousContext); + if (options.afterUpdate) options.afterUpdate(component); + } + var fn, cb = component._renderCallbacks; + if (cb) while (fn = cb.pop()) fn.call(component); + if (!diffLevel && !isChild) flushMounts(); + } + } + function buildComponentFromVNode(dom, vnode, context, mountAll) { + var c = dom && dom._component, oldDom = dom, isDirectOwner = c && dom._componentConstructor === vnode.nodeName, isOwner = isDirectOwner, props = getNodeProps(vnode); + while (c && !isOwner && (c = c._parentComponent)) isOwner = c.constructor === vnode.nodeName; + if (c && isOwner && (!mountAll || c._component)) { + setComponentProps(c, props, 3, context, mountAll); + dom = c.base; + } else { + if (c && !isDirectOwner) { + unmountComponent(c, !0); + dom = oldDom = null; + } + c = createComponent(vnode.nodeName, props, context); + if (dom && !c.nextBase) { + c.nextBase = dom; + oldDom = null; + } + setComponentProps(c, props, 1, context, mountAll); + dom = c.base; + if (oldDom && dom !== oldDom) { + oldDom._component = null; + recollectNodeTree(oldDom); + } + } + return dom; + } + function unmountComponent(component, remove) { + if (options.beforeUnmount) options.beforeUnmount(component); + var base = component.base; + component._disable = !0; + if (component.componentWillUnmount) component.componentWillUnmount(); + component.base = null; + var inner = component._component; + if (inner) unmountComponent(inner, remove); else if (base) { + if (base[ATTR_KEY] && base[ATTR_KEY].ref) base[ATTR_KEY].ref(null); + component.nextBase = base; + if (remove) { + removeNode(base); + collectComponent(component); + } + removeOrphanedChildren(base.childNodes, !remove); + } + if (component.__ref) component.__ref(null); + if (component.componentDidUnmount) component.componentDidUnmount(); + } + function Component(props, context) { + this._dirty = !0; + this.context = context; + this.props = props; + if (!this.state) this.state = {}; + } + function render(vnode, parent, merge) { + return diff(merge, vnode, {}, !1, parent); + } + var options = {}; + var stack = []; + var lcCache = {}; + var toLowerCase = function(s) { + return lcCache[s] || (lcCache[s] = s.toLowerCase()); + }; + var resolved = 'undefined' != typeof Promise && Promise.resolve(); + var defer = resolved ? function(f) { + resolved.then(f); + } : setTimeout; + var EMPTY = {}; + var ATTR_KEY = 'undefined' != typeof Symbol ? Symbol.for('preactattr') : '__preactattr_'; + var NON_DIMENSION_PROPS = { + boxFlex: 1, + boxFlexGroup: 1, + columnCount: 1, + fillOpacity: 1, + flex: 1, + flexGrow: 1, + flexPositive: 1, + flexShrink: 1, + flexNegative: 1, + fontWeight: 1, + lineClamp: 1, + lineHeight: 1, + opacity: 1, + order: 1, + orphans: 1, + strokeOpacity: 1, + widows: 1, + zIndex: 1, + zoom: 1 + }; + var NON_BUBBLING_EVENTS = { + blur: 1, + error: 1, + focus: 1, + load: 1, + resize: 1, + scroll: 1 + }; + var items = []; + var nodes = {}; + var mounts = []; + var diffLevel = 0; + var isSvgMode = !1; + var components = {}; + extend(Component.prototype, { + linkState: function(key, eventPath) { + var c = this._linkedStates || (this._linkedStates = {}); + return c[key + eventPath] || (c[key + eventPath] = createLinkedState(this, key, eventPath)); + }, + setState: function(state, callback) { + var s = this.state; + if (!this.prevState) this.prevState = clone(s); + extend(s, isFunction(state) ? state(s, this.props) : state); + if (callback) (this._renderCallbacks = this._renderCallbacks || []).push(callback); + enqueueRender(this); + }, + forceUpdate: function() { + renderComponent(this, 2); + }, + render: function() {} + }); + exports.h = h; + exports.cloneElement = cloneElement; + exports.Component = Component; + exports.render = render; + exports.rerender = rerender; + exports.options = options; +}); + +},{}],62:[function(require,module,exports){ +(function (process){ +'use strict'; + +if (!process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = { nextTick: nextTick }; +} else { + module.exports = process +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + + +}).call(this,require('_process')) + +},{"_process":63}],63:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],64:[function(require,module,exports){ +(function (global){ +/*! https://mths.be/punycode v1.4.1 by @mathias */ +;(function(root) { + + /** Detect free variables */ + var freeExports = typeof exports == 'object' && exports && + !exports.nodeType && exports; + var freeModule = typeof module == 'object' && module && + !module.nodeType && module; + var freeGlobal = typeof global == 'object' && global; + if ( + freeGlobal.global === freeGlobal || + freeGlobal.window === freeGlobal || + freeGlobal.self === freeGlobal + ) { + root = freeGlobal; + } + + /** + * The `punycode` object. + * @name punycode + * @type Object + */ + var punycode, + + /** Highest positive signed 32-bit float value */ + maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 + + /** Bootstring parameters */ + base = 36, + tMin = 1, + tMax = 26, + skew = 38, + damp = 700, + initialBias = 72, + initialN = 128, // 0x80 + delimiter = '-', // '\x2D' + + /** Regular expressions */ + regexPunycode = /^xn--/, + regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars + regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators + + /** Error messages */ + errors = { + 'overflow': 'Overflow: input needs wider integers to process', + 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', + 'invalid-input': 'Invalid input' + }, + + /** Convenience shortcuts */ + baseMinusTMin = base - tMin, + floor = Math.floor, + stringFromCharCode = String.fromCharCode, + + /** Temporary variable */ + key; + + /*--------------------------------------------------------------------------*/ + + /** + * A generic error utility function. + * @private + * @param {String} type The error type. + * @returns {Error} Throws a `RangeError` with the applicable error message. + */ + function error(type) { + throw new RangeError(errors[type]); + } + + /** + * A generic `Array#map` utility function. + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function that gets called for every array + * item. + * @returns {Array} A new array of values returned by the callback function. + */ + function map(array, fn) { + var length = array.length; + var result = []; + while (length--) { + result[length] = fn(array[length]); + } + return result; + } + + /** + * A simple `Array#map`-like wrapper to work with domain name strings or email + * addresses. + * @private + * @param {String} domain The domain name or email address. + * @param {Function} callback The function that gets called for every + * character. + * @returns {Array} A new string of characters returned by the callback + * function. + */ + function mapDomain(string, fn) { + var parts = string.split('@'); + var result = ''; + if (parts.length > 1) { + // In email addresses, only the domain name should be punycoded. Leave + // the local part (i.e. everything up to `@`) intact. + result = parts[0] + '@'; + string = parts[1]; + } + // Avoid `split(regex)` for IE8 compatibility. See #17. + string = string.replace(regexSeparators, '\x2E'); + var labels = string.split('.'); + var encoded = map(labels, fn).join('.'); + return result + encoded; + } + + /** + * Creates an array containing the numeric code points of each Unicode + * character in the string. While JavaScript uses UCS-2 internally, + * this function will convert a pair of surrogate halves (each of which + * UCS-2 exposes as separate characters) into a single code point, + * matching UTF-16. + * @see `punycode.ucs2.encode` + * @see + * @memberOf punycode.ucs2 + * @name decode + * @param {String} string The Unicode input string (UCS-2). + * @returns {Array} The new array of code points. + */ + function ucs2decode(string) { + var output = [], + counter = 0, + length = string.length, + value, + extra; + while (counter < length) { + value = string.charCodeAt(counter++); + if (value >= 0xD800 && value <= 0xDBFF && counter < length) { + // high surrogate, and there is a next character + extra = string.charCodeAt(counter++); + if ((extra & 0xFC00) == 0xDC00) { // low surrogate + output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); + } else { + // unmatched surrogate; only append this code unit, in case the next + // code unit is the high surrogate of a surrogate pair + output.push(value); + counter--; + } + } else { + output.push(value); + } + } + return output; + } + + /** + * Creates a string based on an array of numeric code points. + * @see `punycode.ucs2.decode` + * @memberOf punycode.ucs2 + * @name encode + * @param {Array} codePoints The array of numeric code points. + * @returns {String} The new Unicode string (UCS-2). + */ + function ucs2encode(array) { + return map(array, function(value) { + var output = ''; + if (value > 0xFFFF) { + value -= 0x10000; + output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); + value = 0xDC00 | value & 0x3FF; + } + output += stringFromCharCode(value); + return output; + }).join(''); + } + + /** + * Converts a basic code point into a digit/integer. + * @see `digitToBasic()` + * @private + * @param {Number} codePoint The basic numeric code point value. + * @returns {Number} The numeric value of a basic code point (for use in + * representing integers) in the range `0` to `base - 1`, or `base` if + * the code point does not represent a value. + */ + function basicToDigit(codePoint) { + if (codePoint - 48 < 10) { + return codePoint - 22; + } + if (codePoint - 65 < 26) { + return codePoint - 65; + } + if (codePoint - 97 < 26) { + return codePoint - 97; + } + return base; + } + + /** + * Converts a digit/integer into a basic code point. + * @see `basicToDigit()` + * @private + * @param {Number} digit The numeric value of a basic code point. + * @returns {Number} The basic code point whose value (when used for + * representing integers) is `digit`, which needs to be in the range + * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is + * used; else, the lowercase form is used. The behavior is undefined + * if `flag` is non-zero and `digit` has no uppercase form. + */ + function digitToBasic(digit, flag) { + // 0..25 map to ASCII a..z or A..Z + // 26..35 map to ASCII 0..9 + return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); + } + + /** + * Bias adaptation function as per section 3.4 of RFC 3492. + * https://tools.ietf.org/html/rfc3492#section-3.4 + * @private + */ + function adapt(delta, numPoints, firstTime) { + var k = 0; + delta = firstTime ? floor(delta / damp) : delta >> 1; + delta += floor(delta / numPoints); + for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { + delta = floor(delta / baseMinusTMin); + } + return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); + } + + /** + * Converts a Punycode string of ASCII-only symbols to a string of Unicode + * symbols. + * @memberOf punycode + * @param {String} input The Punycode string of ASCII-only symbols. + * @returns {String} The resulting string of Unicode symbols. + */ + function decode(input) { + // Don't use UCS-2 + var output = [], + inputLength = input.length, + out, + i = 0, + n = initialN, + bias = initialBias, + basic, + j, + index, + oldi, + w, + k, + digit, + t, + /** Cached calculation results */ + baseMinusT; + + // Handle the basic code points: let `basic` be the number of input code + // points before the last delimiter, or `0` if there is none, then copy + // the first basic code points to the output. + + basic = input.lastIndexOf(delimiter); + if (basic < 0) { + basic = 0; + } + + for (j = 0; j < basic; ++j) { + // if it's not a basic code point + if (input.charCodeAt(j) >= 0x80) { + error('not-basic'); + } + output.push(input.charCodeAt(j)); + } + + // Main decoding loop: start just after the last delimiter if any basic code + // points were copied; start at the beginning otherwise. + + for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { + + // `index` is the index of the next character to be consumed. + // Decode a generalized variable-length integer into `delta`, + // which gets added to `i`. The overflow checking is easier + // if we increase `i` as we go, then subtract off its starting + // value at the end to obtain `delta`. + for (oldi = i, w = 1, k = base; /* no condition */; k += base) { + + if (index >= inputLength) { + error('invalid-input'); + } + + digit = basicToDigit(input.charCodeAt(index++)); + + if (digit >= base || digit > floor((maxInt - i) / w)) { + error('overflow'); + } + + i += digit * w; + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + + if (digit < t) { + break; + } + + baseMinusT = base - t; + if (w > floor(maxInt / baseMinusT)) { + error('overflow'); + } + + w *= baseMinusT; + + } + + out = output.length + 1; + bias = adapt(i - oldi, out, oldi == 0); + + // `i` was supposed to wrap around from `out` to `0`, + // incrementing `n` each time, so we'll fix that now: + if (floor(i / out) > maxInt - n) { + error('overflow'); + } + + n += floor(i / out); + i %= out; + + // Insert `n` at position `i` of the output + output.splice(i++, 0, n); + + } + + return ucs2encode(output); + } + + /** + * Converts a string of Unicode symbols (e.g. a domain name label) to a + * Punycode string of ASCII-only symbols. + * @memberOf punycode + * @param {String} input The string of Unicode symbols. + * @returns {String} The resulting Punycode string of ASCII-only symbols. + */ + function encode(input) { + var n, + delta, + handledCPCount, + basicLength, + bias, + j, + m, + q, + k, + t, + currentValue, + output = [], + /** `inputLength` will hold the number of code points in `input`. */ + inputLength, + /** Cached calculation results */ + handledCPCountPlusOne, + baseMinusT, + qMinusT; + + // Convert the input in UCS-2 to Unicode + input = ucs2decode(input); + + // Cache the length + inputLength = input.length; + + // Initialize the state + n = initialN; + delta = 0; + bias = initialBias; + + // Handle the basic code points + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue < 0x80) { + output.push(stringFromCharCode(currentValue)); + } + } + + handledCPCount = basicLength = output.length; + + // `handledCPCount` is the number of code points that have been handled; + // `basicLength` is the number of basic code points. + + // Finish the basic string - if it is not empty - with a delimiter + if (basicLength) { + output.push(delimiter); + } + + // Main encoding loop: + while (handledCPCount < inputLength) { + + // All non-basic code points < n have been handled already. Find the next + // larger one: + for (m = maxInt, j = 0; j < inputLength; ++j) { + currentValue = input[j]; + if (currentValue >= n && currentValue < m) { + m = currentValue; + } + } + + // Increase `delta` enough to advance the decoder's state to , + // but guard against overflow + handledCPCountPlusOne = handledCPCount + 1; + if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { + error('overflow'); + } + + delta += (m - n) * handledCPCountPlusOne; + n = m; + + for (j = 0; j < inputLength; ++j) { + currentValue = input[j]; + + if (currentValue < n && ++delta > maxInt) { + error('overflow'); + } + + if (currentValue == n) { + // Represent delta as a generalized variable-length integer + for (q = delta, k = base; /* no condition */; k += base) { + t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); + if (q < t) { + break; + } + qMinusT = q - t; + baseMinusT = base - t; + output.push( + stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) + ); + q = floor(qMinusT / baseMinusT); + } + + output.push(stringFromCharCode(digitToBasic(q, 0))); + bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); + delta = 0; + ++handledCPCount; + } + } + + ++delta; + ++n; + + } + return output.join(''); + } + + /** + * Converts a Punycode string representing a domain name or an email address + * to Unicode. Only the Punycoded parts of the input will be converted, i.e. + * it doesn't matter if you call it on a string that has already been + * converted to Unicode. + * @memberOf punycode + * @param {String} input The Punycoded domain name or email address to + * convert to Unicode. + * @returns {String} The Unicode representation of the given Punycode + * string. + */ + function toUnicode(input) { + return mapDomain(input, function(string) { + return regexPunycode.test(string) + ? decode(string.slice(4).toLowerCase()) + : string; + }); + } + + /** + * Converts a Unicode string representing a domain name or an email address to + * Punycode. Only the non-ASCII parts of the domain name will be converted, + * i.e. it doesn't matter if you call it with a domain that's already in + * ASCII. + * @memberOf punycode + * @param {String} input The domain name or email address to convert, as a + * Unicode string. + * @returns {String} The Punycode representation of the given domain name or + * email address. + */ + function toASCII(input) { + return mapDomain(input, function(string) { + return regexNonASCII.test(string) + ? 'xn--' + encode(string) + : string; + }); + } + + /*--------------------------------------------------------------------------*/ + + /** Define the public API */ + punycode = { + /** + * A string representing the current Punycode.js version number. + * @memberOf punycode + * @type String + */ + 'version': '1.4.1', + /** + * An object of methods to convert from JavaScript's internal character + * representation (UCS-2) to Unicode code points, and back. + * @see + * @memberOf punycode + * @type Object + */ + 'ucs2': { + 'decode': ucs2decode, + 'encode': ucs2encode + }, + 'decode': decode, + 'encode': encode, + 'toASCII': toASCII, + 'toUnicode': toUnicode + }; + + /** Expose `punycode` */ + // Some AMD build optimizers, like r.js, check for specific condition patterns + // like the following: + if ( + typeof define == 'function' && + typeof define.amd == 'object' && + define.amd + ) { + define('punycode', function() { + return punycode; + }); + } else if (freeExports && freeModule) { + if (module.exports == freeExports) { + // in Node.js, io.js, or RingoJS v0.8.0+ + freeModule.exports = punycode; + } else { + // in Narwhal or RingoJS v0.7.0- + for (key in punycode) { + punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); + } + } + } else { + // in Rhino or a web browser + root.punycode = punycode; + } + +}(this)); + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],65:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +// If obj.hasOwnProperty has been overridden, then calling +// obj.hasOwnProperty(prop) will break. +// See: https://github.com/joyent/node/issues/1707 +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +module.exports = function(qs, sep, eq, options) { + sep = sep || '&'; + eq = eq || '='; + var obj = {}; + + if (typeof qs !== 'string' || qs.length === 0) { + return obj; + } + + var regexp = /\+/g; + qs = qs.split(sep); + + var maxKeys = 1000; + if (options && typeof options.maxKeys === 'number') { + maxKeys = options.maxKeys; + } + + var len = qs.length; + // maxKeys <= 0 means that we should not limit keys count + if (maxKeys > 0 && len > maxKeys) { + len = maxKeys; + } + + for (var i = 0; i < len; ++i) { + var x = qs[i].replace(regexp, '%20'), + idx = x.indexOf(eq), + kstr, vstr, k, v; + + if (idx >= 0) { + kstr = x.substr(0, idx); + vstr = x.substr(idx + 1); + } else { + kstr = x; + vstr = ''; + } + + k = decodeURIComponent(kstr); + v = decodeURIComponent(vstr); + + if (!hasOwnProperty(obj, k)) { + obj[k] = v; + } else if (isArray(obj[k])) { + obj[k].push(v); + } else { + obj[k] = [obj[k], v]; + } + } + + return obj; +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +},{}],66:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +var stringifyPrimitive = function(v) { + switch (typeof v) { + case 'string': + return v; + + case 'boolean': + return v ? 'true' : 'false'; + + case 'number': + return isFinite(v) ? v : ''; + + default: + return ''; + } +}; + +module.exports = function(obj, sep, eq, name) { + sep = sep || '&'; + eq = eq || '='; + if (obj === null) { + obj = undefined; + } + + if (typeof obj === 'object') { + return map(objectKeys(obj), function(k) { + var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; + if (isArray(obj[k])) { + return map(obj[k], function(v) { + return ks + encodeURIComponent(stringifyPrimitive(v)); + }).join(sep); + } else { + return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + } + }).join(sep); + + } + + if (!name) return ''; + return encodeURIComponent(stringifyPrimitive(name)) + eq + + encodeURIComponent(stringifyPrimitive(obj)); +}; + +var isArray = Array.isArray || function (xs) { + return Object.prototype.toString.call(xs) === '[object Array]'; +}; + +function map (xs, f) { + if (xs.map) return xs.map(f); + var res = []; + for (var i = 0; i < xs.length; i++) { + res.push(f(xs[i], i)); + } + return res; +} + +var objectKeys = Object.keys || function (obj) { + var res = []; + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); + } + return res; +}; + +},{}],67:[function(require,module,exports){ +'use strict'; + +exports.decode = exports.parse = require('./decode'); +exports.encode = exports.stringify = require('./encode'); + +},{"./decode":65,"./encode":66}],68:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; +},{"./_stream_readable":70,"./_stream_writable":72,"core-util-is":22,"inherits":58,"process-nextick-args":62}],69:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; +},{"./_stream_transform":71,"core-util-is":22,"inherits":58}],70:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./_stream_duplex":68,"./internal/streams/BufferList":73,"./internal/streams/destroy":74,"./internal/streams/stream":75,"_process":63,"core-util-is":22,"events":55,"inherits":58,"isarray":60,"process-nextick-args":62,"safe-buffer":77,"string_decoder/":82,"util":18}],71:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} +},{"./_stream_duplex":68,"core-util-is":22,"inherits":58}],72:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./_stream_duplex":68,"./internal/streams/destroy":74,"./internal/streams/stream":75,"_process":63,"core-util-is":22,"inherits":58,"process-nextick-args":62,"safe-buffer":77,"util-deprecate":86}],73:[function(require,module,exports){ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('safe-buffer').Buffer; +var util = require('util'); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} +},{"safe-buffer":77,"util":18}],74:[function(require,module,exports){ +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + pna.nextTick(emitErrorNT, this, err); + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + pna.nextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; +},{"process-nextick-args":62}],75:[function(require,module,exports){ +module.exports = require('events').EventEmitter; + +},{"events":55}],76:[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":68,"./lib/_stream_passthrough.js":69,"./lib/_stream_readable.js":70,"./lib/_stream_transform.js":71,"./lib/_stream_writable.js":72}],77:[function(require,module,exports){ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"buffer":20}],78:[function(require,module,exports){ +(function (global){ +var ClientRequest = require('./lib/request') +var response = require('./lib/response') +var extend = require('xtend') +var statusCodes = require('builtin-status-codes') +var url = require('url') + +var http = exports + +http.request = function (opts, cb) { + if (typeof opts === 'string') + opts = url.parse(opts) + else + opts = extend(opts) + + // Normally, the page is loaded from http or https, so not specifying a protocol + // will result in a (valid) protocol-relative url. However, this won't work if + // the protocol is something else, like 'file:' + var defaultProtocol = global.location.protocol.search(/^https?:$/) === -1 ? 'http:' : '' + + var protocol = opts.protocol || defaultProtocol + var host = opts.hostname || opts.host + var port = opts.port + var path = opts.path || '/' + + // Necessary for IPv6 addresses + if (host && host.indexOf(':') !== -1) + host = '[' + host + ']' + + // This may be a relative url. The browser should always be able to interpret it correctly. + opts.url = (host ? (protocol + '//' + host) : '') + (port ? ':' + port : '') + path + opts.method = (opts.method || 'GET').toUpperCase() + opts.headers = opts.headers || {} + + // Also valid opts.auth, opts.mode + + var req = new ClientRequest(opts) + if (cb) + req.on('response', cb) + return req +} + +http.get = function get (opts, cb) { + var req = http.request(opts, cb) + req.end() + return req +} + +http.ClientRequest = ClientRequest +http.IncomingMessage = response.IncomingMessage + +http.Agent = function () {} +http.Agent.defaultMaxSockets = 4 + +http.globalAgent = new http.Agent() + +http.STATUS_CODES = statusCodes + +http.METHODS = [ + 'CHECKOUT', + 'CONNECT', + 'COPY', + 'DELETE', + 'GET', + 'HEAD', + 'LOCK', + 'M-SEARCH', + 'MERGE', + 'MKACTIVITY', + 'MKCOL', + 'MOVE', + 'NOTIFY', + 'OPTIONS', + 'PATCH', + 'POST', + 'PROPFIND', + 'PROPPATCH', + 'PURGE', + 'PUT', + 'REPORT', + 'SEARCH', + 'SUBSCRIBE', + 'TRACE', + 'UNLOCK', + 'UNSUBSCRIBE' +] +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./lib/request":80,"./lib/response":81,"builtin-status-codes":21,"url":84,"xtend":88}],79:[function(require,module,exports){ +(function (global){ +exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream) + +exports.writableStream = isFunction(global.WritableStream) + +exports.abortController = isFunction(global.AbortController) + +exports.blobConstructor = false +try { + new Blob([new ArrayBuffer(1)]) + exports.blobConstructor = true +} catch (e) {} + +// The xhr request to example.com may violate some restrictive CSP configurations, +// so if we're running in a browser that supports `fetch`, avoid calling getXHR() +// and assume support for certain features below. +var xhr +function getXHR () { + // Cache the xhr value + if (xhr !== undefined) return xhr + + if (global.XMLHttpRequest) { + xhr = new global.XMLHttpRequest() + // If XDomainRequest is available (ie only, where xhr might not work + // cross domain), use the page location. Otherwise use example.com + // Note: this doesn't actually make an http request. + try { + xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com') + } catch(e) { + xhr = null + } + } else { + // Service workers don't have XHR + xhr = null + } + return xhr +} + +function checkTypeSupport (type) { + var xhr = getXHR() + if (!xhr) return false + try { + xhr.responseType = type + return xhr.responseType === type + } catch (e) {} + return false +} + +// For some strange reason, Safari 7.0 reports typeof global.ArrayBuffer === 'object'. +// Safari 7.1 appears to have fixed this bug. +var haveArrayBuffer = typeof global.ArrayBuffer !== 'undefined' +var haveSlice = haveArrayBuffer && isFunction(global.ArrayBuffer.prototype.slice) + +// If fetch is supported, then arraybuffer will be supported too. Skip calling +// checkTypeSupport(), since that calls getXHR(). +exports.arraybuffer = exports.fetch || (haveArrayBuffer && checkTypeSupport('arraybuffer')) + +// These next two tests unavoidably show warnings in Chrome. Since fetch will always +// be used if it's available, just return false for these to avoid the warnings. +exports.msstream = !exports.fetch && haveSlice && checkTypeSupport('ms-stream') +exports.mozchunkedarraybuffer = !exports.fetch && haveArrayBuffer && + checkTypeSupport('moz-chunked-arraybuffer') + +// If fetch is supported, then overrideMimeType will be supported too. Skip calling +// getXHR(). +exports.overrideMimeType = exports.fetch || (getXHR() ? isFunction(getXHR().overrideMimeType) : false) + +exports.vbArray = isFunction(global.VBArray) + +function isFunction (value) { + return typeof value === 'function' +} + +xhr = null // Help gc + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],80:[function(require,module,exports){ +(function (process,global,Buffer){ +var capability = require('./capability') +var inherits = require('inherits') +var response = require('./response') +var stream = require('readable-stream') +var toArrayBuffer = require('to-arraybuffer') + +var IncomingMessage = response.IncomingMessage +var rStates = response.readyStates + +function decideMode (preferBinary, useFetch) { + if (capability.fetch && useFetch) { + return 'fetch' + } else if (capability.mozchunkedarraybuffer) { + return 'moz-chunked-arraybuffer' + } else if (capability.msstream) { + return 'ms-stream' + } else if (capability.arraybuffer && preferBinary) { + return 'arraybuffer' + } else if (capability.vbArray && preferBinary) { + return 'text:vbarray' + } else { + return 'text' + } +} + +var ClientRequest = module.exports = function (opts) { + var self = this + stream.Writable.call(self) + + self._opts = opts + self._body = [] + self._headers = {} + if (opts.auth) + self.setHeader('Authorization', 'Basic ' + new Buffer(opts.auth).toString('base64')) + Object.keys(opts.headers).forEach(function (name) { + self.setHeader(name, opts.headers[name]) + }) + + var preferBinary + var useFetch = true + if (opts.mode === 'disable-fetch' || ('requestTimeout' in opts && !capability.abortController)) { + // If the use of XHR should be preferred. Not typically needed. + useFetch = false + preferBinary = true + } else if (opts.mode === 'prefer-streaming') { + // If streaming is a high priority but binary compatibility and + // the accuracy of the 'content-type' header aren't + preferBinary = false + } else if (opts.mode === 'allow-wrong-content-type') { + // If streaming is more important than preserving the 'content-type' header + preferBinary = !capability.overrideMimeType + } else if (!opts.mode || opts.mode === 'default' || opts.mode === 'prefer-fast') { + // Use binary if text streaming may corrupt data or the content-type header, or for speed + preferBinary = true + } else { + throw new Error('Invalid value for opts.mode') + } + self._mode = decideMode(preferBinary, useFetch) + + self.on('finish', function () { + self._onFinish() + }) +} + +inherits(ClientRequest, stream.Writable) + +ClientRequest.prototype.setHeader = function (name, value) { + var self = this + var lowerName = name.toLowerCase() + // This check is not necessary, but it prevents warnings from browsers about setting unsafe + // headers. To be honest I'm not entirely sure hiding these warnings is a good thing, but + // http-browserify did it, so I will too. + if (unsafeHeaders.indexOf(lowerName) !== -1) + return + + self._headers[lowerName] = { + name: name, + value: value + } +} + +ClientRequest.prototype.getHeader = function (name) { + var header = this._headers[name.toLowerCase()] + if (header) + return header.value + return null +} + +ClientRequest.prototype.removeHeader = function (name) { + var self = this + delete self._headers[name.toLowerCase()] +} + +ClientRequest.prototype._onFinish = function () { + var self = this + + if (self._destroyed) + return + var opts = self._opts + + var headersObj = self._headers + var body = null + if (opts.method !== 'GET' && opts.method !== 'HEAD') { + if (capability.arraybuffer) { + body = toArrayBuffer(Buffer.concat(self._body)) + } else if (capability.blobConstructor) { + body = new global.Blob(self._body.map(function (buffer) { + return toArrayBuffer(buffer) + }), { + type: (headersObj['content-type'] || {}).value || '' + }) + } else { + // get utf8 string + body = Buffer.concat(self._body).toString() + } + } + + // create flattened list of headers + var headersList = [] + Object.keys(headersObj).forEach(function (keyName) { + var name = headersObj[keyName].name + var value = headersObj[keyName].value + if (Array.isArray(value)) { + value.forEach(function (v) { + headersList.push([name, v]) + }) + } else { + headersList.push([name, value]) + } + }) + + if (self._mode === 'fetch') { + var signal = null + if (capability.abortController) { + var controller = new AbortController() + signal = controller.signal + self._fetchAbortController = controller + + if ('requestTimeout' in opts && opts.requestTimeout !== 0) { + global.setTimeout(function () { + self.emit('requestTimeout') + if (self._fetchAbortController) + self._fetchAbortController.abort() + }, opts.requestTimeout) + } + } + + global.fetch(self._opts.url, { + method: self._opts.method, + headers: headersList, + body: body || undefined, + mode: 'cors', + credentials: opts.withCredentials ? 'include' : 'same-origin', + signal: signal + }).then(function (response) { + self._fetchResponse = response + self._connect() + }, function (reason) { + self.emit('error', reason) + }) + } else { + var xhr = self._xhr = new global.XMLHttpRequest() + try { + xhr.open(self._opts.method, self._opts.url, true) + } catch (err) { + process.nextTick(function () { + self.emit('error', err) + }) + return + } + + // Can't set responseType on really old browsers + if ('responseType' in xhr) + xhr.responseType = self._mode.split(':')[0] + + if ('withCredentials' in xhr) + xhr.withCredentials = !!opts.withCredentials + + if (self._mode === 'text' && 'overrideMimeType' in xhr) + xhr.overrideMimeType('text/plain; charset=x-user-defined') + + if ('requestTimeout' in opts) { + xhr.timeout = opts.requestTimeout + xhr.ontimeout = function () { + self.emit('requestTimeout') + } + } + + headersList.forEach(function (header) { + xhr.setRequestHeader(header[0], header[1]) + }) + + self._response = null + xhr.onreadystatechange = function () { + switch (xhr.readyState) { + case rStates.LOADING: + case rStates.DONE: + self._onXHRProgress() + break + } + } + // Necessary for streaming in Firefox, since xhr.response is ONLY defined + // in onprogress, not in onreadystatechange with xhr.readyState = 3 + if (self._mode === 'moz-chunked-arraybuffer') { + xhr.onprogress = function () { + self._onXHRProgress() + } + } + + xhr.onerror = function () { + if (self._destroyed) + return + self.emit('error', new Error('XHR error')) + } + + try { + xhr.send(body) + } catch (err) { + process.nextTick(function () { + self.emit('error', err) + }) + return + } + } +} + +/** + * Checks if xhr.status is readable and non-zero, indicating no error. + * Even though the spec says it should be available in readyState 3, + * accessing it throws an exception in IE8 + */ +function statusValid (xhr) { + try { + var status = xhr.status + return (status !== null && status !== 0) + } catch (e) { + return false + } +} + +ClientRequest.prototype._onXHRProgress = function () { + var self = this + + if (!statusValid(self._xhr) || self._destroyed) + return + + if (!self._response) + self._connect() + + self._response._onXHRProgress() +} + +ClientRequest.prototype._connect = function () { + var self = this + + if (self._destroyed) + return + + self._response = new IncomingMessage(self._xhr, self._fetchResponse, self._mode) + self._response.on('error', function(err) { + self.emit('error', err) + }) + + self.emit('response', self._response) +} + +ClientRequest.prototype._write = function (chunk, encoding, cb) { + var self = this + + self._body.push(chunk) + cb() +} + +ClientRequest.prototype.abort = ClientRequest.prototype.destroy = function () { + var self = this + self._destroyed = true + if (self._response) + self._response._destroyed = true + if (self._xhr) + self._xhr.abort() + else if (self._fetchAbortController) + self._fetchAbortController.abort() +} + +ClientRequest.prototype.end = function (data, encoding, cb) { + var self = this + if (typeof data === 'function') { + cb = data + data = undefined + } + + stream.Writable.prototype.end.call(self, data, encoding, cb) +} + +ClientRequest.prototype.flushHeaders = function () {} +ClientRequest.prototype.setTimeout = function () {} +ClientRequest.prototype.setNoDelay = function () {} +ClientRequest.prototype.setSocketKeepAlive = function () {} + +// Taken from http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader%28%29-method +var unsafeHeaders = [ + 'accept-charset', + 'accept-encoding', + 'access-control-request-headers', + 'access-control-request-method', + 'connection', + 'content-length', + 'cookie', + 'cookie2', + 'date', + 'dnt', + 'expect', + 'host', + 'keep-alive', + 'origin', + 'referer', + 'te', + 'trailer', + 'transfer-encoding', + 'upgrade', + 'user-agent', + 'via' +] + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) + +},{"./capability":79,"./response":81,"_process":63,"buffer":20,"inherits":58,"readable-stream":76,"to-arraybuffer":83}],81:[function(require,module,exports){ +(function (process,global,Buffer){ +var capability = require('./capability') +var inherits = require('inherits') +var stream = require('readable-stream') + +var rStates = exports.readyStates = { + UNSENT: 0, + OPENED: 1, + HEADERS_RECEIVED: 2, + LOADING: 3, + DONE: 4 +} + +var IncomingMessage = exports.IncomingMessage = function (xhr, response, mode) { + var self = this + stream.Readable.call(self) + + self._mode = mode + self.headers = {} + self.rawHeaders = [] + self.trailers = {} + self.rawTrailers = [] + + // Fake the 'close' event, but only once 'end' fires + self.on('end', function () { + // The nextTick is necessary to prevent the 'request' module from causing an infinite loop + process.nextTick(function () { + self.emit('close') + }) + }) + + if (mode === 'fetch') { + self._fetchResponse = response + + self.url = response.url + self.statusCode = response.status + self.statusMessage = response.statusText + + response.headers.forEach(function (header, key){ + self.headers[key.toLowerCase()] = header + self.rawHeaders.push(key, header) + }) + + if (capability.writableStream) { + var writable = new WritableStream({ + write: function (chunk) { + return new Promise(function (resolve, reject) { + if (self._destroyed) { + return + } else if(self.push(new Buffer(chunk))) { + resolve() + } else { + self._resumeFetch = resolve + } + }) + }, + close: function () { + if (!self._destroyed) + self.push(null) + }, + abort: function (err) { + if (!self._destroyed) + self.emit('error', err) + } + }) + + try { + response.body.pipeTo(writable) + return + } catch (e) {} // pipeTo method isn't defined. Can't find a better way to feature test this + } + // fallback for when writableStream or pipeTo aren't available + var reader = response.body.getReader() + function read () { + reader.read().then(function (result) { + if (self._destroyed) + return + if (result.done) { + self.push(null) + return + } + self.push(new Buffer(result.value)) + read() + }).catch(function(err) { + if (!self._destroyed) + self.emit('error', err) + }) + } + read() + } else { + self._xhr = xhr + self._pos = 0 + + self.url = xhr.responseURL + self.statusCode = xhr.status + self.statusMessage = xhr.statusText + var headers = xhr.getAllResponseHeaders().split(/\r?\n/) + headers.forEach(function (header) { + var matches = header.match(/^([^:]+):\s*(.*)/) + if (matches) { + var key = matches[1].toLowerCase() + if (key === 'set-cookie') { + if (self.headers[key] === undefined) { + self.headers[key] = [] + } + self.headers[key].push(matches[2]) + } else if (self.headers[key] !== undefined) { + self.headers[key] += ', ' + matches[2] + } else { + self.headers[key] = matches[2] + } + self.rawHeaders.push(matches[1], matches[2]) + } + }) + + self._charset = 'x-user-defined' + if (!capability.overrideMimeType) { + var mimeType = self.rawHeaders['mime-type'] + if (mimeType) { + var charsetMatch = mimeType.match(/;\s*charset=([^;])(;|$)/) + if (charsetMatch) { + self._charset = charsetMatch[1].toLowerCase() + } + } + if (!self._charset) + self._charset = 'utf-8' // best guess + } + } +} + +inherits(IncomingMessage, stream.Readable) + +IncomingMessage.prototype._read = function () { + var self = this + + var resolve = self._resumeFetch + if (resolve) { + self._resumeFetch = null + resolve() + } +} + +IncomingMessage.prototype._onXHRProgress = function () { + var self = this + + var xhr = self._xhr + + var response = null + switch (self._mode) { + case 'text:vbarray': // For IE9 + if (xhr.readyState !== rStates.DONE) + break + try { + // This fails in IE8 + response = new global.VBArray(xhr.responseBody).toArray() + } catch (e) {} + if (response !== null) { + self.push(new Buffer(response)) + break + } + // Falls through in IE8 + case 'text': + try { // This will fail when readyState = 3 in IE9. Switch mode and wait for readyState = 4 + response = xhr.responseText + } catch (e) { + self._mode = 'text:vbarray' + break + } + if (response.length > self._pos) { + var newData = response.substr(self._pos) + if (self._charset === 'x-user-defined') { + var buffer = new Buffer(newData.length) + for (var i = 0; i < newData.length; i++) + buffer[i] = newData.charCodeAt(i) & 0xff + + self.push(buffer) + } else { + self.push(newData, self._charset) + } + self._pos = response.length + } + break + case 'arraybuffer': + if (xhr.readyState !== rStates.DONE || !xhr.response) + break + response = xhr.response + self.push(new Buffer(new Uint8Array(response))) + break + case 'moz-chunked-arraybuffer': // take whole + response = xhr.response + if (xhr.readyState !== rStates.LOADING || !response) + break + self.push(new Buffer(new Uint8Array(response))) + break + case 'ms-stream': + response = xhr.response + if (xhr.readyState !== rStates.LOADING) + break + var reader = new global.MSStreamReader() + reader.onprogress = function () { + if (reader.result.byteLength > self._pos) { + self.push(new Buffer(new Uint8Array(reader.result.slice(self._pos)))) + self._pos = reader.result.byteLength + } + } + reader.onload = function () { + self.push(null) + } + // reader.onerror = ??? // TODO: this + reader.readAsArrayBuffer(response) + break + } + + // The ms-stream case handles end separately in reader.onload() + if (self._xhr.readyState === rStates.DONE && self._mode !== 'ms-stream') { + self.push(null) + } +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer) + +},{"./capability":79,"_process":63,"buffer":20,"inherits":58,"readable-stream":76}],82:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var Buffer = require('safe-buffer').Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"safe-buffer":77}],83:[function(require,module,exports){ +var Buffer = require('buffer').Buffer + +module.exports = function (buf) { + // If the buffer is backed by a Uint8Array, a faster version will work + if (buf instanceof Uint8Array) { + // If the buffer isn't a subarray, return the underlying ArrayBuffer + if (buf.byteOffset === 0 && buf.byteLength === buf.buffer.byteLength) { + return buf.buffer + } else if (typeof buf.buffer.slice === 'function') { + // Otherwise we need to get a proper copy + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) + } + } + + if (Buffer.isBuffer(buf)) { + // This is the slow version that will work with any Buffer + // implementation (even in old browsers) + var arrayCopy = new Uint8Array(buf.length) + var len = buf.length + for (var i = 0; i < len; i++) { + arrayCopy[i] = buf[i] + } + return arrayCopy.buffer + } else { + throw new Error('Argument must be a Buffer') + } +} + +},{"buffer":20}],84:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +var punycode = require('punycode'); +var util = require('./util'); + +exports.parse = urlParse; +exports.resolve = urlResolve; +exports.resolveObject = urlResolveObject; +exports.format = urlFormat; + +exports.Url = Url; + +function Url() { + this.protocol = null; + this.slashes = null; + this.auth = null; + this.host = null; + this.port = null; + this.hostname = null; + this.hash = null; + this.search = null; + this.query = null; + this.pathname = null; + this.path = null; + this.href = null; +} + +// Reference: RFC 3986, RFC 1808, RFC 2396 + +// define these here so at least they only have to be +// compiled once on the first module load. +var protocolPattern = /^([a-z0-9.+-]+:)/i, + portPattern = /:[0-9]*$/, + + // Special case for a simple path URL + simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, + + // RFC 2396: characters reserved for delimiting URLs. + // We actually just auto-escape these. + delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], + + // RFC 2396: characters not allowed for various reasons. + unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), + + // Allowed by RFCs, but cause of XSS attacks. Always escape these. + autoEscape = ['\''].concat(unwise), + // Characters that are never ever allowed in a hostname. + // Note that any invalid chars are also handled, but these + // are the ones that are *expected* to be seen, so we fast-path + // them. + nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), + hostEndingChars = ['/', '?', '#'], + hostnameMaxLen = 255, + hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, + hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, + // protocols that can allow "unsafe" and "unwise" chars. + unsafeProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that never have a hostname. + hostlessProtocol = { + 'javascript': true, + 'javascript:': true + }, + // protocols that always contain a // bit. + slashedProtocol = { + 'http': true, + 'https': true, + 'ftp': true, + 'gopher': true, + 'file': true, + 'http:': true, + 'https:': true, + 'ftp:': true, + 'gopher:': true, + 'file:': true + }, + querystring = require('querystring'); + +function urlParse(url, parseQueryString, slashesDenoteHost) { + if (url && util.isObject(url) && url instanceof Url) return url; + + var u = new Url; + u.parse(url, parseQueryString, slashesDenoteHost); + return u; +} + +Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { + if (!util.isString(url)) { + throw new TypeError("Parameter 'url' must be a string, not " + typeof url); + } + + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + var queryIndex = url.indexOf('?'), + splitter = + (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', + uSplit = url.split(splitter), + slashRegex = /\\/g; + uSplit[0] = uSplit[0].replace(slashRegex, '/'); + url = uSplit.join(splitter); + + var rest = url; + + // trim before proceeding. + // This is to support parse stuff like " http://foo.com \n" + rest = rest.trim(); + + if (!slashesDenoteHost && url.split('#').length === 1) { + // Try fast path regexp + var simplePath = simplePathPattern.exec(rest); + if (simplePath) { + this.path = rest; + this.href = rest; + this.pathname = simplePath[1]; + if (simplePath[2]) { + this.search = simplePath[2]; + if (parseQueryString) { + this.query = querystring.parse(this.search.substr(1)); + } else { + this.query = this.search.substr(1); + } + } else if (parseQueryString) { + this.search = ''; + this.query = {}; + } + return this; + } + } + + var proto = protocolPattern.exec(rest); + if (proto) { + proto = proto[0]; + var lowerProto = proto.toLowerCase(); + this.protocol = lowerProto; + rest = rest.substr(proto.length); + } + + // figure out if it's got a host + // user@server is *always* interpreted as a hostname, and url + // resolution will treat //foo/bar as host=foo,path=bar because that's + // how the browser resolves relative URLs. + if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { + var slashes = rest.substr(0, 2) === '//'; + if (slashes && !(proto && hostlessProtocol[proto])) { + rest = rest.substr(2); + this.slashes = true; + } + } + + if (!hostlessProtocol[proto] && + (slashes || (proto && !slashedProtocol[proto]))) { + + // there's a hostname. + // the first instance of /, ?, ;, or # ends the host. + // + // If there is an @ in the hostname, then non-host chars *are* allowed + // to the left of the last @ sign, unless some host-ending character + // comes *before* the @-sign. + // URLs are obnoxious. + // + // ex: + // http://a@b@c/ => user:a@b host:c + // http://a@b?@c => user:a host:c path:/?@c + + // v0.12 TODO(isaacs): This is not quite how Chrome does things. + // Review our test case against browsers more comprehensively. + + // find the first instance of any hostEndingChars + var hostEnd = -1; + for (var i = 0; i < hostEndingChars.length; i++) { + var hec = rest.indexOf(hostEndingChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + + // at this point, either we have an explicit point where the + // auth portion cannot go past, or the last @ char is the decider. + var auth, atSign; + if (hostEnd === -1) { + // atSign can be anywhere. + atSign = rest.lastIndexOf('@'); + } else { + // atSign must be in auth portion. + // http://a@b/c@d => host:b auth:a path:/c@d + atSign = rest.lastIndexOf('@', hostEnd); + } + + // Now we have a portion which is definitely the auth. + // Pull that off. + if (atSign !== -1) { + auth = rest.slice(0, atSign); + rest = rest.slice(atSign + 1); + this.auth = decodeURIComponent(auth); + } + + // the host is the remaining to the left of the first non-host char + hostEnd = -1; + for (var i = 0; i < nonHostChars.length; i++) { + var hec = rest.indexOf(nonHostChars[i]); + if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) + hostEnd = hec; + } + // if we still have not hit it, then the entire thing is a host. + if (hostEnd === -1) + hostEnd = rest.length; + + this.host = rest.slice(0, hostEnd); + rest = rest.slice(hostEnd); + + // pull out port. + this.parseHost(); + + // we've indicated that there is a hostname, + // so even if it's empty, it has to be present. + this.hostname = this.hostname || ''; + + // if hostname begins with [ and ends with ] + // assume that it's an IPv6 address. + var ipv6Hostname = this.hostname[0] === '[' && + this.hostname[this.hostname.length - 1] === ']'; + + // validate a little. + if (!ipv6Hostname) { + var hostparts = this.hostname.split(/\./); + for (var i = 0, l = hostparts.length; i < l; i++) { + var part = hostparts[i]; + if (!part) continue; + if (!part.match(hostnamePartPattern)) { + var newpart = ''; + for (var j = 0, k = part.length; j < k; j++) { + if (part.charCodeAt(j) > 127) { + // we replace non-ASCII char with a temporary placeholder + // we need this to make sure size of hostname is not + // broken by replacing non-ASCII by nothing + newpart += 'x'; + } else { + newpart += part[j]; + } + } + // we test again with ASCII char only + if (!newpart.match(hostnamePartPattern)) { + var validParts = hostparts.slice(0, i); + var notHost = hostparts.slice(i + 1); + var bit = part.match(hostnamePartStart); + if (bit) { + validParts.push(bit[1]); + notHost.unshift(bit[2]); + } + if (notHost.length) { + rest = '/' + notHost.join('.') + rest; + } + this.hostname = validParts.join('.'); + break; + } + } + } + } + + if (this.hostname.length > hostnameMaxLen) { + this.hostname = ''; + } else { + // hostnames are always lower case. + this.hostname = this.hostname.toLowerCase(); + } + + if (!ipv6Hostname) { + // IDNA Support: Returns a punycoded representation of "domain". + // It only converts parts of the domain name that + // have non-ASCII characters, i.e. it doesn't matter if + // you call it with a domain that already is ASCII-only. + this.hostname = punycode.toASCII(this.hostname); + } + + var p = this.port ? ':' + this.port : ''; + var h = this.hostname || ''; + this.host = h + p; + this.href += this.host; + + // strip [ and ] from the hostname + // the host field still retains them, though + if (ipv6Hostname) { + this.hostname = this.hostname.substr(1, this.hostname.length - 2); + if (rest[0] !== '/') { + rest = '/' + rest; + } + } + } + + // now rest is set to the post-host stuff. + // chop off any delim chars. + if (!unsafeProtocol[lowerProto]) { + + // First, make 100% sure that any "autoEscape" chars get + // escaped, even if encodeURIComponent doesn't think they + // need to be. + for (var i = 0, l = autoEscape.length; i < l; i++) { + var ae = autoEscape[i]; + if (rest.indexOf(ae) === -1) + continue; + var esc = encodeURIComponent(ae); + if (esc === ae) { + esc = escape(ae); + } + rest = rest.split(ae).join(esc); + } + } + + + // chop off from the tail first. + var hash = rest.indexOf('#'); + if (hash !== -1) { + // got a fragment string. + this.hash = rest.substr(hash); + rest = rest.slice(0, hash); + } + var qm = rest.indexOf('?'); + if (qm !== -1) { + this.search = rest.substr(qm); + this.query = rest.substr(qm + 1); + if (parseQueryString) { + this.query = querystring.parse(this.query); + } + rest = rest.slice(0, qm); + } else if (parseQueryString) { + // no query string, but parseQueryString still requested + this.search = ''; + this.query = {}; + } + if (rest) this.pathname = rest; + if (slashedProtocol[lowerProto] && + this.hostname && !this.pathname) { + this.pathname = '/'; + } + + //to support http.request + if (this.pathname || this.search) { + var p = this.pathname || ''; + var s = this.search || ''; + this.path = p + s; + } + + // finally, reconstruct the href based on what has been validated. + this.href = this.format(); + return this; +}; + +// format a parsed object into a url string +function urlFormat(obj) { + // ensure it's an object, and not a string url. + // If it's an obj, this is a no-op. + // this way, you can call url_format() on strings + // to clean up potentially wonky urls. + if (util.isString(obj)) obj = urlParse(obj); + if (!(obj instanceof Url)) return Url.prototype.format.call(obj); + return obj.format(); +} + +Url.prototype.format = function() { + var auth = this.auth || ''; + if (auth) { + auth = encodeURIComponent(auth); + auth = auth.replace(/%3A/i, ':'); + auth += '@'; + } + + var protocol = this.protocol || '', + pathname = this.pathname || '', + hash = this.hash || '', + host = false, + query = ''; + + if (this.host) { + host = auth + this.host; + } else if (this.hostname) { + host = auth + (this.hostname.indexOf(':') === -1 ? + this.hostname : + '[' + this.hostname + ']'); + if (this.port) { + host += ':' + this.port; + } + } + + if (this.query && + util.isObject(this.query) && + Object.keys(this.query).length) { + query = querystring.stringify(this.query); + } + + var search = this.search || (query && ('?' + query)) || ''; + + if (protocol && protocol.substr(-1) !== ':') protocol += ':'; + + // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. + // unless they had them to begin with. + if (this.slashes || + (!protocol || slashedProtocol[protocol]) && host !== false) { + host = '//' + (host || ''); + if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; + } else if (!host) { + host = ''; + } + + if (hash && hash.charAt(0) !== '#') hash = '#' + hash; + if (search && search.charAt(0) !== '?') search = '?' + search; + + pathname = pathname.replace(/[?#]/g, function(match) { + return encodeURIComponent(match); + }); + search = search.replace('#', '%23'); + + return protocol + host + pathname + search + hash; +}; + +function urlResolve(source, relative) { + return urlParse(source, false, true).resolve(relative); +} + +Url.prototype.resolve = function(relative) { + return this.resolveObject(urlParse(relative, false, true)).format(); +}; + +function urlResolveObject(source, relative) { + if (!source) return relative; + return urlParse(source, false, true).resolveObject(relative); +} + +Url.prototype.resolveObject = function(relative) { + if (util.isString(relative)) { + var rel = new Url(); + rel.parse(relative, false, true); + relative = rel; + } + + var result = new Url(); + var tkeys = Object.keys(this); + for (var tk = 0; tk < tkeys.length; tk++) { + var tkey = tkeys[tk]; + result[tkey] = this[tkey]; + } + + // hash is always overridden, no matter what. + // even href="" will remove it. + result.hash = relative.hash; + + // if the relative url is empty, then there's nothing left to do here. + if (relative.href === '') { + result.href = result.format(); + return result; + } + + // hrefs like //foo/bar always cut to the protocol. + if (relative.slashes && !relative.protocol) { + // take everything except the protocol from relative + var rkeys = Object.keys(relative); + for (var rk = 0; rk < rkeys.length; rk++) { + var rkey = rkeys[rk]; + if (rkey !== 'protocol') + result[rkey] = relative[rkey]; + } + + //urlParse appends trailing / to urls like http://www.example.com + if (slashedProtocol[result.protocol] && + result.hostname && !result.pathname) { + result.path = result.pathname = '/'; + } + + result.href = result.format(); + return result; + } + + if (relative.protocol && relative.protocol !== result.protocol) { + // if it's a known url protocol, then changing + // the protocol does weird things + // first, if it's not file:, then we MUST have a host, + // and if there was a path + // to begin with, then we MUST have a path. + // if it is file:, then the host is dropped, + // because that's known to be hostless. + // anything else is assumed to be absolute. + if (!slashedProtocol[relative.protocol]) { + var keys = Object.keys(relative); + for (var v = 0; v < keys.length; v++) { + var k = keys[v]; + result[k] = relative[k]; + } + result.href = result.format(); + return result; + } + + result.protocol = relative.protocol; + if (!relative.host && !hostlessProtocol[relative.protocol]) { + var relPath = (relative.pathname || '').split('/'); + while (relPath.length && !(relative.host = relPath.shift())); + if (!relative.host) relative.host = ''; + if (!relative.hostname) relative.hostname = ''; + if (relPath[0] !== '') relPath.unshift(''); + if (relPath.length < 2) relPath.unshift(''); + result.pathname = relPath.join('/'); + } else { + result.pathname = relative.pathname; + } + result.search = relative.search; + result.query = relative.query; + result.host = relative.host || ''; + result.auth = relative.auth; + result.hostname = relative.hostname || relative.host; + result.port = relative.port; + // to support http.request + if (result.pathname || result.search) { + var p = result.pathname || ''; + var s = result.search || ''; + result.path = p + s; + } + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; + } + + var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), + isRelAbs = ( + relative.host || + relative.pathname && relative.pathname.charAt(0) === '/' + ), + mustEndAbs = (isRelAbs || isSourceAbs || + (result.host && relative.pathname)), + removeAllDots = mustEndAbs, + srcPath = result.pathname && result.pathname.split('/') || [], + relPath = relative.pathname && relative.pathname.split('/') || [], + psychotic = result.protocol && !slashedProtocol[result.protocol]; + + // if the url is a non-slashed url, then relative + // links like ../.. should be able + // to crawl up to the hostname, as well. This is strange. + // result.protocol has already been set by now. + // Later on, put the first path part into the host field. + if (psychotic) { + result.hostname = ''; + result.port = null; + if (result.host) { + if (srcPath[0] === '') srcPath[0] = result.host; + else srcPath.unshift(result.host); + } + result.host = ''; + if (relative.protocol) { + relative.hostname = null; + relative.port = null; + if (relative.host) { + if (relPath[0] === '') relPath[0] = relative.host; + else relPath.unshift(relative.host); + } + relative.host = null; + } + mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); + } + + if (isRelAbs) { + // it's absolute. + result.host = (relative.host || relative.host === '') ? + relative.host : result.host; + result.hostname = (relative.hostname || relative.hostname === '') ? + relative.hostname : result.hostname; + result.search = relative.search; + result.query = relative.query; + srcPath = relPath; + // fall through to the dot-handling below. + } else if (relPath.length) { + // it's relative + // throw away the existing file, and take the new path instead. + if (!srcPath) srcPath = []; + srcPath.pop(); + srcPath = srcPath.concat(relPath); + result.search = relative.search; + result.query = relative.query; + } else if (!util.isNullOrUndefined(relative.search)) { + // just pull out the search. + // like href='?foo'. + // Put this after the other two cases because it simplifies the booleans + if (psychotic) { + result.hostname = result.host = srcPath.shift(); + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + result.search = relative.search; + result.query = relative.query; + //to support http.request + if (!util.isNull(result.pathname) || !util.isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.href = result.format(); + return result; + } + + if (!srcPath.length) { + // no path at all. easy. + // we've already handled the other stuff above. + result.pathname = null; + //to support http.request + if (result.search) { + result.path = '/' + result.search; + } else { + result.path = null; + } + result.href = result.format(); + return result; + } + + // if a url ENDs in . or .., then it must get a trailing slash. + // however, if it ends in anything else non-slashy, + // then it must NOT get a trailing slash. + var last = srcPath.slice(-1)[0]; + var hasTrailingSlash = ( + (result.host || relative.host || srcPath.length > 1) && + (last === '.' || last === '..') || last === ''); + + // strip single dots, resolve double dots to parent dir + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = srcPath.length; i >= 0; i--) { + last = srcPath[i]; + if (last === '.') { + srcPath.splice(i, 1); + } else if (last === '..') { + srcPath.splice(i, 1); + up++; + } else if (up) { + srcPath.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (!mustEndAbs && !removeAllDots) { + for (; up--; up) { + srcPath.unshift('..'); + } + } + + if (mustEndAbs && srcPath[0] !== '' && + (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { + srcPath.unshift(''); + } + + if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { + srcPath.push(''); + } + + var isAbsolute = srcPath[0] === '' || + (srcPath[0] && srcPath[0].charAt(0) === '/'); + + // put the host back + if (psychotic) { + result.hostname = result.host = isAbsolute ? '' : + srcPath.length ? srcPath.shift() : ''; + //occationaly the auth can get stuck only in host + //this especially happens in cases like + //url.resolveObject('mailto:local1@domain1', 'local2@domain2') + var authInHost = result.host && result.host.indexOf('@') > 0 ? + result.host.split('@') : false; + if (authInHost) { + result.auth = authInHost.shift(); + result.host = result.hostname = authInHost.shift(); + } + } + + mustEndAbs = mustEndAbs || (result.host && srcPath.length); + + if (mustEndAbs && !isAbsolute) { + srcPath.unshift(''); + } + + if (!srcPath.length) { + result.pathname = null; + result.path = null; + } else { + result.pathname = srcPath.join('/'); + } + + //to support request.http + if (!util.isNull(result.pathname) || !util.isNull(result.search)) { + result.path = (result.pathname ? result.pathname : '') + + (result.search ? result.search : ''); + } + result.auth = relative.auth || result.auth; + result.slashes = result.slashes || relative.slashes; + result.href = result.format(); + return result; +}; + +Url.prototype.parseHost = function() { + var host = this.host; + var port = portPattern.exec(host); + if (port) { + port = port[0]; + if (port !== ':') { + this.port = port.substr(1); + } + host = host.substr(0, host.length - port.length); + } + if (host) this.hostname = host; +}; + +},{"./util":85,"punycode":64,"querystring":67}],85:[function(require,module,exports){ +'use strict'; + +module.exports = { + isString: function(arg) { + return typeof(arg) === 'string'; + }, + isObject: function(arg) { + return typeof(arg) === 'object' && arg !== null; + }, + isNull: function(arg) { + return arg === null; + }, + isNullOrUndefined: function(arg) { + return arg == null; + } +}; + +},{}],86:[function(require,module,exports){ +(function (global){ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],87:[function(require,module,exports){ +(function (process,Buffer){ +/** + * Wrapper for built-in http.js to emulate the browser XMLHttpRequest object. + * + * This can be used with JS designed for browsers to improve reuse of code and + * allow the use of existing libraries. + * + * Usage: include("XMLHttpRequest.js") and use XMLHttpRequest per W3C specs. + * + * @author Dan DeFelippi + * @contributor David Ellis + * @license MIT + */ + +var Url = require("url"); +var spawn = require("child_process").spawn; +var fs = require("fs"); + +exports.XMLHttpRequest = function() { + "use strict"; + + /** + * Private variables + */ + var self = this; + var http = require("http"); + var https = require("https"); + + // Holds http.js objects + var request; + var response; + + // Request settings + var settings = {}; + + // Disable header blacklist. + // Not part of XHR specs. + var disableHeaderCheck = false; + + // Set some default headers + var defaultHeaders = { + "User-Agent": "node-XMLHttpRequest", + "Accept": "*/*", + }; + + var headers = {}; + var headersCase = {}; + + // These headers are not user setable. + // The following are allowed but banned in the spec: + // * user-agent + var forbiddenRequestHeaders = [ + "accept-charset", + "accept-encoding", + "access-control-request-headers", + "access-control-request-method", + "connection", + "content-length", + "content-transfer-encoding", + "cookie", + "cookie2", + "date", + "expect", + "host", + "keep-alive", + "origin", + "referer", + "te", + "trailer", + "transfer-encoding", + "upgrade", + "via" + ]; + + // These request methods are not allowed + var forbiddenRequestMethods = [ + "TRACE", + "TRACK", + "CONNECT" + ]; + + // Send flag + var sendFlag = false; + // Error flag, used when errors occur or abort is called + var errorFlag = false; + + // Event listeners + var listeners = {}; + + /** + * Constants + */ + + this.UNSENT = 0; + this.OPENED = 1; + this.HEADERS_RECEIVED = 2; + this.LOADING = 3; + this.DONE = 4; + + /** + * Public vars + */ + + // Current state + this.readyState = this.UNSENT; + + // default ready state change handler in case one is not set or is set late + this.onreadystatechange = null; + + // Result & response + this.responseText = ""; + this.responseXML = ""; + this.status = null; + this.statusText = null; + + // Whether cross-site Access-Control requests should be made using + // credentials such as cookies or authorization headers + this.withCredentials = false; + + /** + * Private methods + */ + + /** + * Check if the specified header is allowed. + * + * @param string header Header to validate + * @return boolean False if not allowed, otherwise true + */ + var isAllowedHttpHeader = function(header) { + return disableHeaderCheck || (header && forbiddenRequestHeaders.indexOf(header.toLowerCase()) === -1); + }; + + /** + * Check if the specified method is allowed. + * + * @param string method Request method to validate + * @return boolean False if not allowed, otherwise true + */ + var isAllowedHttpMethod = function(method) { + return (method && forbiddenRequestMethods.indexOf(method) === -1); + }; + + /** + * Public methods + */ + + /** + * Open the connection. Currently supports local server requests. + * + * @param string method Connection method (eg GET, POST) + * @param string url URL for the connection. + * @param boolean async Asynchronous connection. Default is true. + * @param string user Username for basic authentication (optional) + * @param string password Password for basic authentication (optional) + */ + this.open = function(method, url, async, user, password) { + this.abort(); + errorFlag = false; + + // Check for valid request method + if (!isAllowedHttpMethod(method)) { + throw new Error("SecurityError: Request method not allowed"); + } + + settings = { + "method": method, + "url": url.toString(), + "async": (typeof async !== "boolean" ? true : async), + "user": user || null, + "password": password || null + }; + + setState(this.OPENED); + }; + + /** + * Disables or enables isAllowedHttpHeader() check the request. Enabled by default. + * This does not conform to the W3C spec. + * + * @param boolean state Enable or disable header checking. + */ + this.setDisableHeaderCheck = function(state) { + disableHeaderCheck = state; + }; + + /** + * Sets a header for the request or appends the value if one is already set. + * + * @param string header Header name + * @param string value Header value + */ + this.setRequestHeader = function(header, value) { + if (this.readyState !== this.OPENED) { + throw new Error("INVALID_STATE_ERR: setRequestHeader can only be called when state is OPEN"); + } + if (!isAllowedHttpHeader(header)) { + console.warn("Refused to set unsafe header \"" + header + "\""); + return; + } + if (sendFlag) { + throw new Error("INVALID_STATE_ERR: send flag is true"); + } + header = headersCase[header.toLowerCase()] || header; + headersCase[header.toLowerCase()] = header; + headers[header] = headers[header] ? headers[header] + ', ' + value : value; + }; + + /** + * Gets a header from the server response. + * + * @param string header Name of header to get. + * @return string Text of the header or null if it doesn't exist. + */ + this.getResponseHeader = function(header) { + if (typeof header === "string" + && this.readyState > this.OPENED + && response + && response.headers + && response.headers[header.toLowerCase()] + && !errorFlag + ) { + return response.headers[header.toLowerCase()]; + } + + return null; + }; + + /** + * Gets all the response headers. + * + * @return string A string with all response headers separated by CR+LF + */ + this.getAllResponseHeaders = function() { + if (this.readyState < this.HEADERS_RECEIVED || errorFlag) { + return ""; + } + var result = ""; + + for (var i in response.headers) { + // Cookie headers are excluded + if (i !== "set-cookie" && i !== "set-cookie2") { + result += i + ": " + response.headers[i] + "\r\n"; + } + } + return result.substr(0, result.length - 2); + }; + + /** + * Gets a request header + * + * @param string name Name of header to get + * @return string Returns the request header or empty string if not set + */ + this.getRequestHeader = function(name) { + if (typeof name === "string" && headersCase[name.toLowerCase()]) { + return headers[headersCase[name.toLowerCase()]]; + } + + return ""; + }; + + /** + * Sends the request to the server. + * + * @param string data Optional data to send as request body. + */ + this.send = function(data) { + if (this.readyState !== this.OPENED) { + throw new Error("INVALID_STATE_ERR: connection must be opened before send() is called"); + } + + if (sendFlag) { + throw new Error("INVALID_STATE_ERR: send has already been called"); + } + + var ssl = false, local = false; + var url = Url.parse(settings.url); + var host; + // Determine the server + switch (url.protocol) { + case "https:": + ssl = true; + // SSL & non-SSL both need host, no break here. + case "http:": + host = url.hostname; + break; + + case "file:": + local = true; + break; + + case undefined: + case null: + case "": + host = "localhost"; + break; + + default: + throw new Error("Protocol not supported."); + } + + // Load files off the local filesystem (file://) + if (local) { + if (settings.method !== "GET") { + throw new Error("XMLHttpRequest: Only GET method is supported"); + } + + if (settings.async) { + fs.readFile(url.pathname, "utf8", function(error, data) { + if (error) { + self.handleError(error); + } else { + self.status = 200; + self.responseText = data; + setState(self.DONE); + } + }); + } else { + try { + this.responseText = fs.readFileSync(url.pathname, "utf8"); + this.status = 200; + setState(self.DONE); + } catch(e) { + this.handleError(e); + } + } + + return; + } + + // Default to port 80. If accessing localhost on another port be sure + // to use http://localhost:port/path + var port = url.port || (ssl ? 443 : 80); + // Add query string if one is used + var uri = url.pathname + (url.search ? url.search : ""); + + // Set the defaults if they haven't been set + for (var name in defaultHeaders) { + if (!headersCase[name.toLowerCase()]) { + headers[name] = defaultHeaders[name]; + } + } + + // Set the Host header or the server may reject the request + headers.Host = host; + if (!((ssl && port === 443) || port === 80)) { + headers.Host += ":" + url.port; + } + + // Set Basic Auth if necessary + if (settings.user) { + if (typeof settings.password === "undefined") { + settings.password = ""; + } + var authBuf = new Buffer(settings.user + ":" + settings.password); + headers.Authorization = "Basic " + authBuf.toString("base64"); + } + + // Set content length header + if (settings.method === "GET" || settings.method === "HEAD") { + data = null; + } else if (data) { + headers["Content-Length"] = Buffer.isBuffer(data) ? data.length : Buffer.byteLength(data); + + if (!headers["Content-Type"]) { + headers["Content-Type"] = "text/plain;charset=UTF-8"; + } + } else if (settings.method === "POST") { + // For a post with no data set Content-Length: 0. + // This is required by buggy servers that don't meet the specs. + headers["Content-Length"] = 0; + } + + var options = { + host: host, + port: port, + path: uri, + method: settings.method, + headers: headers, + agent: false, + withCredentials: self.withCredentials + }; + + // Reset error flag + errorFlag = false; + + // Handle async requests + if (settings.async) { + // Use the proper protocol + var doRequest = ssl ? https.request : http.request; + + // Request is being sent, set send flag + sendFlag = true; + + // As per spec, this is called here for historical reasons. + self.dispatchEvent("readystatechange"); + + // Handler for the response + var responseHandler = function responseHandler(resp) { + // Set response var to the response we got back + // This is so it remains accessable outside this scope + response = resp; + // Check for redirect + // @TODO Prevent looped redirects + if (response.statusCode === 301 || response.statusCode === 302 || response.statusCode === 303 || response.statusCode === 307) { + // Change URL to the redirect location + settings.url = response.headers.location; + var url = Url.parse(settings.url); + // Set host var in case it's used later + host = url.hostname; + // Options for the new request + var newOptions = { + hostname: url.hostname, + port: url.port, + path: url.path, + method: response.statusCode === 303 ? "GET" : settings.method, + headers: headers, + withCredentials: self.withCredentials + }; + + // Issue the new request + request = doRequest(newOptions, responseHandler).on("error", errorHandler); + request.end(); + // @TODO Check if an XHR event needs to be fired here + return; + } + + response.setEncoding("utf8"); + + setState(self.HEADERS_RECEIVED); + self.status = response.statusCode; + + response.on("data", function(chunk) { + // Make sure there's some data + if (chunk) { + self.responseText += chunk; + } + // Don't emit state changes if the connection has been aborted. + if (sendFlag) { + setState(self.LOADING); + } + }); + + response.on("end", function() { + if (sendFlag) { + // Discard the end event if the connection has been aborted + setState(self.DONE); + sendFlag = false; + } + }); + + response.on("error", function(error) { + self.handleError(error); + }); + }; + + // Error handler for the request + var errorHandler = function errorHandler(error) { + self.handleError(error); + }; + + // Create the request + request = doRequest(options, responseHandler).on("error", errorHandler); + + // Node 0.4 and later won't accept empty data. Make sure it's needed. + if (data) { + request.write(data); + } + + request.end(); + + self.dispatchEvent("loadstart"); + } else { // Synchronous + // Create a temporary file for communication with the other Node process + var contentFile = ".node-xmlhttprequest-content-" + process.pid; + var syncFile = ".node-xmlhttprequest-sync-" + process.pid; + fs.writeFileSync(syncFile, "", "utf8"); + // The async request the other Node process executes + var execString = "var http = require('http'), https = require('https'), fs = require('fs');" + + "var doRequest = http" + (ssl ? "s" : "") + ".request;" + + "var options = " + JSON.stringify(options) + ";" + + "var responseText = '';" + + "var req = doRequest(options, function(response) {" + + "response.setEncoding('utf8');" + + "response.on('data', function(chunk) {" + + " responseText += chunk;" + + "});" + + "response.on('end', function() {" + + "fs.writeFileSync('" + contentFile + "', JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText}}), 'utf8');" + + "fs.unlinkSync('" + syncFile + "');" + + "});" + + "response.on('error', function(error) {" + + "fs.writeFileSync('" + contentFile + "', JSON.stringify({err: error}), 'utf8');" + + "fs.unlinkSync('" + syncFile + "');" + + "});" + + "}).on('error', function(error) {" + + "fs.writeFileSync('" + contentFile + "', JSON.stringify({err: error}), 'utf8');" + + "fs.unlinkSync('" + syncFile + "');" + + "});" + + (data ? "req.write('" + JSON.stringify(data).slice(1,-1).replace(/'/g, "\\'") + "');":"") + + "req.end();"; + // Start the other Node Process, executing this string + var syncProc = spawn(process.argv[0], ["-e", execString]); + while(fs.existsSync(syncFile)) { + // Wait while the sync file is empty + } + var resp = JSON.parse(fs.readFileSync(contentFile, 'utf8')); + // Kill the child process once the file has data + syncProc.stdin.end(); + // Remove the temporary file + fs.unlinkSync(contentFile); + + if (resp.err) { + self.handleError(resp.err); + } else { + response = resp.data; + self.status = resp.data.statusCode; + self.responseText = resp.data.text; + setState(self.DONE); + } + } + }; + + /** + * Called when an error is encountered to deal with it. + */ + this.handleError = function(error) { + this.status = 0; + this.statusText = error; + this.responseText = error.stack; + errorFlag = true; + setState(this.DONE); + this.dispatchEvent('error'); + }; + + /** + * Aborts a request. + */ + this.abort = function() { + if (request) { + request.abort(); + request = null; + } + + headers = defaultHeaders; + this.status = 0; + this.responseText = ""; + this.responseXML = ""; + + errorFlag = true; + + if (this.readyState !== this.UNSENT + && (this.readyState !== this.OPENED || sendFlag) + && this.readyState !== this.DONE) { + sendFlag = false; + setState(this.DONE); + } + this.readyState = this.UNSENT; + this.dispatchEvent('abort'); + }; + + /** + * Adds an event listener. Preferred method of binding to events. + */ + this.addEventListener = function(event, callback) { + if (!(event in listeners)) { + listeners[event] = []; + } + // Currently allows duplicate callbacks. Should it? + listeners[event].push(callback); + }; + + /** + * Remove an event callback that has already been bound. + * Only works on the matching funciton, cannot be a copy. + */ + this.removeEventListener = function(event, callback) { + if (event in listeners) { + // Filter will return a new array with the callback removed + listeners[event] = listeners[event].filter(function(ev) { + return ev !== callback; + }); + } + }; + + /** + * Dispatch any events, including both "on" methods and events attached using addEventListener. + */ + this.dispatchEvent = function(event) { + if (typeof self["on" + event] === "function") { + self["on" + event](); + } + if (event in listeners) { + for (var i = 0, len = listeners[event].length; i < len; i++) { + listeners[event][i].call(self); + } + } + }; + + /** + * Changes readyState and calls onreadystatechange. + * + * @param int state New state + */ + var setState = function(state) { + if (state == self.LOADING || self.readyState !== state) { + self.readyState = state; + + if (settings.async || self.readyState < self.OPENED || self.readyState === self.DONE) { + self.dispatchEvent("readystatechange"); + } + + if (self.readyState === self.DONE && !errorFlag) { + self.dispatchEvent("load"); + // @TODO figure out InspectorInstrumentation::didLoadXHR(cookie) + self.dispatchEvent("loadend"); + } + } + }; +}; + +}).call(this,require('_process'),require("buffer").Buffer) + +},{"_process":63,"buffer":20,"child_process":19,"fs":19,"http":78,"https":56,"url":84}],88:[function(require,module,exports){ +module.exports = extend + +var hasOwnProperty = Object.prototype.hasOwnProperty; + +function extend() { + var target = {} + + for (var i = 0; i < arguments.length; i++) { + var source = arguments[i] + + for (var key in source) { + if (hasOwnProperty.call(source, key)) { + target[key] = source[key] + } + } + } + + return target +} + +},{}]},{},[16]) +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJhc3NldHMvc3JjL2pzL2NvbXBvbmVudHMvQ291bnRXaWRnZXQuanMiLCJhc3NldHMvc3JjL2pzL2NvbXBvbmVudHMvRGF0ZVBpY2tlci5qcyIsImFzc2V0cy9zcmMvanMvY29tcG9uZW50cy9HcmFwaC5qcyIsImFzc2V0cy9zcmMvanMvY29tcG9uZW50cy9HcmFwaFdpZGdldC5qcyIsImFzc2V0cy9zcmMvanMvY29tcG9uZW50cy9IZWFkZXJCYXIuanMiLCJhc3NldHMvc3JjL2pzL2NvbXBvbmVudHMvTG9naW5Gb3JtLmpzIiwiYXNzZXRzL3NyYy9qcy9jb21wb25lbnRzL0xvZ291dEJ1dHRvbi5qcyIsImFzc2V0cy9zcmMvanMvY29tcG9uZW50cy9Ob3RpZmljYXRpb24uanMiLCJhc3NldHMvc3JjL2pzL2NvbXBvbmVudHMvUGFnZXZpZXdzLmpzIiwiYXNzZXRzL3NyYy9qcy9jb21wb25lbnRzL1JlYWx0aW1lLmpzIiwiYXNzZXRzL3NyYy9qcy9jb21wb25lbnRzL1RhYmxlLmpzIiwiYXNzZXRzL3NyYy9qcy9saWIvY2xpZW50LmpzIiwiYXNzZXRzL3NyYy9qcy9saWIvbnVtYmVycy5qcyIsImFzc2V0cy9zcmMvanMvcGFnZXMvZGFzaGJvYXJkLmpzIiwiYXNzZXRzL3NyYy9qcy9wYWdlcy9sb2dpbi5qcyIsImFzc2V0cy9zcmMvanMvc2NyaXB0LmpzIiwibm9kZV9tb2R1bGVzL2Jhc2U2NC1qcy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9icm93c2VyLXJlc29sdmUvZW1wdHkuanMiLCJub2RlX21vZHVsZXMvYnVmZmVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2J1aWx0aW4tc3RhdHVzLWNvZGVzL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvY29yZS11dGlsLWlzL2xpYi91dGlsLmpzIiwibm9kZV9tb2R1bGVzL2QzLWFycmF5L2J1aWxkL2QzLWFycmF5LmpzIiwibm9kZV9tb2R1bGVzL2QzLWF4aXMvYnVpbGQvZDMtYXhpcy5qcyIsIm5vZGVfbW9kdWxlcy9kMy1icnVzaC9idWlsZC9kMy1icnVzaC5qcyIsIm5vZGVfbW9kdWxlcy9kMy1jaG9yZC9idWlsZC9kMy1jaG9yZC5qcyIsIm5vZGVfbW9kdWxlcy9kMy1jb2xsZWN0aW9uL2J1aWxkL2QzLWNvbGxlY3Rpb24uanMiLCJub2RlX21vZHVsZXMvZDMtY29sb3IvYnVpbGQvZDMtY29sb3IuanMiLCJub2RlX21vZHVsZXMvZDMtZGlzcGF0Y2gvYnVpbGQvZDMtZGlzcGF0Y2guanMiLCJub2RlX21vZHVsZXMvZDMtZHJhZy9idWlsZC9kMy1kcmFnLmpzIiwibm9kZV9tb2R1bGVzL2QzLWRzdi9idWlsZC9kMy1kc3YuanMiLCJub2RlX21vZHVsZXMvZDMtZWFzZS9idWlsZC9kMy1lYXNlLmpzIiwibm9kZV9tb2R1bGVzL2QzLWZvcmNlL2J1aWxkL2QzLWZvcmNlLmpzIiwibm9kZV9tb2R1bGVzL2QzLWZvcm1hdC9idWlsZC9kMy1mb3JtYXQuanMiLCJub2RlX21vZHVsZXMvZDMtZ2VvL2J1aWxkL2QzLWdlby5qcyIsIm5vZGVfbW9kdWxlcy9kMy1oaWVyYXJjaHkvYnVpbGQvZDMtaGllcmFyY2h5LmpzIiwibm9kZV9tb2R1bGVzL2QzLWludGVycG9sYXRlL2J1aWxkL2QzLWludGVycG9sYXRlLmpzIiwibm9kZV9tb2R1bGVzL2QzLXBhdGgvYnVpbGQvZDMtcGF0aC5qcyIsIm5vZGVfbW9kdWxlcy9kMy1wb2x5Z29uL2J1aWxkL2QzLXBvbHlnb24uanMiLCJub2RlX21vZHVsZXMvZDMtcXVhZHRyZWUvYnVpbGQvZDMtcXVhZHRyZWUuanMiLCJub2RlX21vZHVsZXMvZDMtcXVldWUvYnVpbGQvZDMtcXVldWUuanMiLCJub2RlX21vZHVsZXMvZDMtcmFuZG9tL2J1aWxkL2QzLXJhbmRvbS5qcyIsIm5vZGVfbW9kdWxlcy9kMy1yZXF1ZXN0L2J1aWxkL2QzLXJlcXVlc3Qubm9kZS5qcyIsIm5vZGVfbW9kdWxlcy9kMy1zY2FsZS9idWlsZC9kMy1zY2FsZS5qcyIsIm5vZGVfbW9kdWxlcy9kMy1zZWxlY3Rpb24vZGlzdC9kMy1zZWxlY3Rpb24uanMiLCJub2RlX21vZHVsZXMvZDMtc2hhcGUvYnVpbGQvZDMtc2hhcGUuanMiLCJub2RlX21vZHVsZXMvZDMtdGltZS1mb3JtYXQvYnVpbGQvZDMtdGltZS1mb3JtYXQuanMiLCJub2RlX21vZHVsZXMvZDMtdGltZS9idWlsZC9kMy10aW1lLmpzIiwibm9kZV9tb2R1bGVzL2QzLXRpbWVyL2J1aWxkL2QzLXRpbWVyLmpzIiwibm9kZV9tb2R1bGVzL2QzLXRpcC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9kMy10cmFuc2l0aW9uL2J1aWxkL2QzLXRyYW5zaXRpb24uanMiLCJub2RlX21vZHVsZXMvZDMtdm9yb25vaS9idWlsZC9kMy12b3Jvbm9pLmpzIiwibm9kZV9tb2R1bGVzL2QzLXpvb20vYnVpbGQvZDMtem9vbS5qcyIsIm5vZGVfbW9kdWxlcy9kMy9idWlsZC9kMy5ub2RlLmpzIiwibm9kZV9tb2R1bGVzL2V2ZW50cy9ldmVudHMuanMiLCJub2RlX21vZHVsZXMvaHR0cHMtYnJvd3NlcmlmeS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9pZWVlNzU0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2luaGVyaXRzL2luaGVyaXRzX2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvaXMtYnVmZmVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2lzYXJyYXkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcHJlYWN0L2Rpc3QvcHJlYWN0LmpzIiwibm9kZV9tb2R1bGVzL3Byb2Nlc3MtbmV4dGljay1hcmdzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9wdW55Y29kZS9wdW55Y29kZS5qcyIsIm5vZGVfbW9kdWxlcy9xdWVyeXN0cmluZy1lczMvZGVjb2RlLmpzIiwibm9kZV9tb2R1bGVzL3F1ZXJ5c3RyaW5nLWVzMy9lbmNvZGUuanMiLCJub2RlX21vZHVsZXMvcXVlcnlzdHJpbmctZXMzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3JlYWRhYmxlLXN0cmVhbS9saWIvX3N0cmVhbV9kdXBsZXguanMiLCJub2RlX21vZHVsZXMvcmVhZGFibGUtc3RyZWFtL2xpYi9fc3RyZWFtX3Bhc3N0aHJvdWdoLmpzIiwibm9kZV9tb2R1bGVzL3JlYWRhYmxlLXN0cmVhbS9saWIvX3N0cmVhbV9yZWFkYWJsZS5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vbGliL19zdHJlYW1fdHJhbnNmb3JtLmpzIiwibm9kZV9tb2R1bGVzL3JlYWRhYmxlLXN0cmVhbS9saWIvX3N0cmVhbV93cml0YWJsZS5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vbGliL2ludGVybmFsL3N0cmVhbXMvQnVmZmVyTGlzdC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vbGliL2ludGVybmFsL3N0cmVhbXMvZGVzdHJveS5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vbGliL2ludGVybmFsL3N0cmVhbXMvc3RyZWFtLWJyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcmVhZGFibGUtc3RyZWFtL3JlYWRhYmxlLWJyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvc2FmZS1idWZmZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc3RyZWFtLWh0dHAvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc3RyZWFtLWh0dHAvbGliL2NhcGFiaWxpdHkuanMiLCJub2RlX21vZHVsZXMvc3RyZWFtLWh0dHAvbGliL3JlcXVlc3QuanMiLCJub2RlX21vZHVsZXMvc3RyZWFtLWh0dHAvbGliL3Jlc3BvbnNlLmpzIiwibm9kZV9tb2R1bGVzL3N0cmluZ19kZWNvZGVyL2xpYi9zdHJpbmdfZGVjb2Rlci5qcyIsIm5vZGVfbW9kdWxlcy90by1hcnJheWJ1ZmZlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy91cmwvdXJsLmpzIiwibm9kZV9tb2R1bGVzL3VybC91dGlsLmpzIiwibm9kZV9tb2R1bGVzL3V0aWwtZGVwcmVjYXRlL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMveG1saHR0cHJlcXVlc3QvbGliL1hNTEh0dHBSZXF1ZXN0LmpzIiwibm9kZV9tb2R1bGVzL3h0ZW5kL2ltbXV0YWJsZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBOzs7Ozs7OztBQUVBOztBQUNBOztJQUFZLE87O0FBQ1o7Ozs7Ozs7Ozs7Ozs7O0FBQ0EsSUFBTSxlQUFlLEtBQUssRUFBTCxHQUFVLEVBQS9COztJQUVNLFc7OztBQUNKLHVCQUFZLEtBQVosRUFBbUI7QUFBQTs7QUFBQSwwSEFDWCxLQURXOztBQUdqQixVQUFLLEtBQUwsR0FBYTtBQUNYLGFBQU8sQ0FESTtBQUVYLHFCQUFlLENBRko7QUFHWCxlQUFTO0FBSEUsS0FBYjs7QUFNQSxVQUFLLFNBQUwsR0FBaUIsTUFBSyxTQUFMLENBQWUsSUFBZixPQUFqQjtBQUNBLFVBQUssU0FBTCxDQUFlLE1BQU0sTUFBckI7QUFWaUI7QUFXbEI7Ozs7OENBRXlCLFEsRUFBVTtBQUNsQyxVQUFHLEtBQUssS0FBTCxDQUFXLE1BQVgsSUFBcUIsU0FBUyxNQUFqQyxFQUF5QztBQUN2QyxhQUFLLFNBQUwsQ0FBZSxTQUFTLE1BQXhCO0FBQ0Q7QUFDRjs7OzhCQUVTLE0sRUFBUTtBQUFBOztBQUNoQixVQUFNLFNBQVMsS0FBSyxLQUFMLENBQVksQ0FBQyxJQUFJLElBQUosRUFBRixHQUFpQixJQUE1QixDQUFmO0FBQ0EsVUFBTSxRQUFRLFNBQVcsU0FBUyxZQUFsQztBQUNBLFdBQUssUUFBTCxDQUFjLEVBQUUsU0FBUyxJQUFYLEVBQWQ7O0FBRUEsdUJBQU8sT0FBUCxDQUFrQixLQUFLLEtBQUwsQ0FBVyxRQUE3QixzQkFBc0QsTUFBdEQsZUFBc0UsS0FBdEUsRUFDRyxJQURILENBQ1EsVUFBQyxDQUFELEVBQU87QUFBRSxlQUFLLFFBQUwsQ0FBYyxFQUFFLFNBQVMsS0FBWCxFQUFrQixPQUFPLENBQXpCLEVBQWQ7QUFBNEMsT0FEN0Q7O0FBR0E7QUFDQSxVQUFNLGlCQUFpQixLQUF2QjtBQUNBLFVBQU0sZ0JBQWdCLGlCQUFtQixTQUFTLFlBQWxEO0FBQ0EsdUJBQU8sT0FBUCxDQUFrQixLQUFLLEtBQUwsQ0FBVyxRQUE3QixzQkFBc0QsY0FBdEQsZUFBOEUsYUFBOUUsRUFDRyxJQURILENBQ1EsVUFBQyxDQUFELEVBQU87QUFBRSxlQUFLLFFBQUwsQ0FBYyxFQUFFLGVBQWUsQ0FBakIsRUFBZDtBQUFvQyxPQURyRDtBQUVEOzs7dUNBRWtCO0FBQ2pCO0FBQ0EsVUFBSSxDQUFFLEtBQUssS0FBTCxDQUFXLGFBQWpCLEVBQWlDO0FBQy9CLGVBQU8sRUFBUDtBQUNEOztBQUVELFVBQU0sYUFBYSxLQUFLLEtBQUwsQ0FBYSxLQUFLLEtBQUwsQ0FBVyxLQUFYLEdBQW1CLEtBQUssS0FBTCxDQUFXLGFBQTlCLEdBQThDLEdBQTlDLEdBQW9ELEdBQWpFLENBQW5CO0FBQ0EsYUFDRTtBQUFBO0FBQUEsVUFBTyxTQUFPLGFBQWEsQ0FBYixHQUFpQixVQUFqQixHQUE4QixVQUE1QztBQUF5RCxrQkFBekQ7QUFBQTtBQUFBLE9BREY7QUFHRDs7OzZCQUVRO0FBQ1AsVUFBTSxpQkFBaUIsS0FBSyxLQUFMLENBQVcsT0FBWCxHQUFxQjtBQUFBO0FBQUEsVUFBSyxTQUFNLGlCQUFYO0FBQTZCO0FBQTdCLE9BQXJCLEdBQXNFLEVBQTdGO0FBQ0EsYUFDRTtBQUFBO0FBQUEsVUFBSyxTQUFNLG1CQUFYO0FBQ0csc0JBREg7QUFFRTtBQUFBO0FBQUEsWUFBSSxTQUFNLEVBQVY7QUFBYyxlQUFLLEtBQUwsQ0FBVztBQUF6QixTQUZGO0FBR0U7QUFBQTtBQUFBLFlBQUssU0FBTSxpQkFBWDtBQUE4QixrQkFBUSxlQUFSLENBQXdCLEtBQUssS0FBTCxDQUFXLEtBQW5DLENBQTlCO0FBQUE7QUFBMEUsZUFBSyxnQkFBTDtBQUExRTtBQUhGLE9BREY7QUFPRDs7Ozs7O2tCQUdZLFc7OztBQ2xFZjs7Ozs7Ozs7QUFFQTs7Ozs7Ozs7QUFFQSxJQUFNLG1CQUFtQixDQUN2QjtBQUNFLE1BQUksQ0FETjtBQUVFLFNBQU87QUFGVCxDQUR1QixFQUt2QjtBQUNFLE1BQUksRUFETjtBQUVFLFNBQU87QUFGVCxDQUx1QixFQVN2QjtBQUNFLE1BQUksRUFETjtBQUVFLFNBQU87QUFGVCxDQVR1QixFQWF2QjtBQUNFLE1BQUksR0FETjtBQUVFLFNBQU87QUFGVCxDQWJ1QixDQUF6Qjs7SUFtQk0sVTs7O0FBQ0osc0JBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLHdIQUNYLEtBRFc7O0FBR2pCLFVBQUssS0FBTCxHQUFhO0FBQ1gsY0FBUSxNQUFLLEtBQUwsQ0FBVztBQURSLEtBQWI7O0FBSUEsVUFBSyxTQUFMLEdBQWlCLE1BQUssU0FBTCxDQUFlLElBQWYsT0FBakI7QUFQaUI7QUFRbEI7Ozs7OEJBRVMsQyxFQUFHO0FBQ1gsVUFBSSxZQUFZLEVBQUUsUUFBUSxTQUFTLEVBQUUsTUFBRixDQUFTLEtBQWxCLENBQVYsRUFBaEI7QUFDQSxVQUFHLEtBQUssS0FBTCxDQUFXLE1BQVgsSUFBcUIsVUFBVSxNQUFsQyxFQUEwQztBQUN4QyxhQUFLLFFBQUwsQ0FBYyxTQUFkO0FBQ0EsYUFBSyxLQUFMLENBQVcsUUFBWCxDQUFvQixLQUFLLEtBQUwsQ0FBVyxNQUEvQjtBQUNEO0FBQ0Y7Ozs2QkFFUTtBQUFBOztBQUNQLFVBQU0sVUFBVSxpQkFBaUIsR0FBakIsQ0FBcUIsVUFBQyxDQUFELEVBQU87QUFDMUMsWUFBSSxZQUFjLEVBQUUsRUFBRixJQUFRLE9BQUssS0FBTCxDQUFXLE1BQXJCLEdBQWdDLFFBQWhDLEdBQTJDLEVBQTNEO0FBQ0EsZUFBTztBQUFBO0FBQUEsWUFBUSxPQUFPLEVBQUUsRUFBakIsRUFBcUIsU0FBTyxTQUE1QixFQUF1QyxTQUFTLE9BQUssU0FBckQ7QUFBaUUsWUFBRTtBQUFuRSxTQUFQO0FBQ0QsT0FIZSxDQUFoQjs7QUFLQSxhQUVFO0FBQUE7QUFBQSxVQUFLLFNBQU0sY0FBWDtBQUNHO0FBREgsT0FGRjtBQU1EOzs7Ozs7a0JBR1ksVTs7O0FDekRmOzs7Ozs7OztBQUVBOztBQUNBOzs7O0FBQ0E7O0lBQVksTzs7QUFFWjs7SUFBWSxFOzs7Ozs7Ozs7Ozs7QUFDWixHQUFHLEdBQUgsR0FBUyxRQUFRLFFBQVIsQ0FBVDs7QUFFQSxJQUFNLGVBQWUsS0FBSyxFQUFMLEdBQVUsRUFBL0I7O0FBRUEsU0FBUyxLQUFULENBQWUsT0FBZixFQUF3QixXQUF4QixFQUFxQyxhQUFyQyxFQUFvRDtBQUNsRCxNQUFJLE9BQU8sRUFBWDtBQUFBLE1BQWUsT0FBTyxFQUF0QjtBQUFBLE1BQTBCLE9BQU8sRUFBakM7QUFBQSxNQUFxQyxPQUFPLEVBQTVDO0FBQUEsTUFDSSxJQUFJLEdBRFI7QUFBQSxNQUVJLElBQUksUUFBUSxVQUFSLENBQW1CLFdBQW5CLEdBQWlDLElBQWpDLEdBQXdDLElBRmhEO0FBQUEsTUFHSSxJQUFLLEdBQUcsU0FBSCxHQUFlLEtBQWYsQ0FBcUIsQ0FBQyxDQUFELEVBQUksQ0FBSixDQUFyQixFQUE2QixPQUE3QixDQUFxQyxHQUFyQyxFQUEwQyxLQUExQyxDQUFnRCxJQUFoRCxDQUhUO0FBQUEsTUFJSSxJQUFLLEdBQUcsV0FBSCxHQUFpQixLQUFqQixDQUF1QixDQUFDLENBQUQsRUFBSSxDQUFKLENBQXZCLENBSlQ7QUFBQSxNQUtJLFFBQVEsR0FBRyxRQUFILEdBQWMsS0FBZCxDQUFvQixDQUFwQixFQUF1QixRQUF2QixDQUFnQyxDQUFDLENBQUQsR0FBSyxJQUFMLEdBQVksSUFBNUMsQ0FMWjtBQUFBLE1BTUksUUFBUSxHQUFHLFVBQUgsR0FBZ0IsS0FBaEIsQ0FBc0IsQ0FBdEIsQ0FOWjtBQUFBLE1BT0ksY0FBYyxFQVBsQjtBQUFBLE1BUUksZ0JBQWdCLEVBUnBCOztBQVVBLE1BQUksY0FBYyxHQUFHLEdBQUgsR0FDYixJQURhLENBQ1IsT0FEUSxFQUNDLFFBREQsRUFFYixJQUZhLENBRVIsVUFBQyxDQUFEO0FBQUEsV0FBTyxTQUFRLEVBQUUsS0FBVixHQUFpQixhQUFqQixHQUFpQyxRQUFRLGVBQVIsQ0FBd0IsRUFBRSxLQUExQixDQUFqQyxHQUFvRSxTQUFwRSxHQUFnRixZQUF2RjtBQUFBLEdBRlEsRUFHYixNQUhhLENBR04sQ0FBQyxDQUFDLEVBQUYsRUFBTSxDQUFOLENBSE0sQ0FBbEI7O0FBS0EsTUFBSSxhQUFhLEdBQUcsR0FBSCxHQUNaLElBRFksQ0FDUCxPQURPLEVBQ0UsUUFERixFQUVaLElBRlksQ0FFUCxVQUFDLENBQUQ7QUFBQSxXQUFPLFNBQVEsRUFBRSxLQUFWLEdBQWlCLGFBQWpCLEdBQWlDLFFBQVEsZUFBUixDQUF3QixFQUFFLEtBQTFCLENBQWpDLEdBQW9FLFNBQXBFLEdBQWdGLFdBQXZGO0FBQUEsR0FGTyxFQUdaLE1BSFksQ0FHTCxDQUFDLENBQUMsRUFBRixFQUFNLENBQU4sQ0FISyxDQUFqQjs7QUFLQSxNQUFJLFFBQVEsR0FBRyxNQUFILENBQVUsUUFBVixDQUFaO0FBQ0EsTUFBSSxNQUFNLE1BQ0wsTUFESyxDQUNFLEtBREYsRUFFTCxJQUZLLENBRUEsT0FGQSxFQUVTLElBQUksSUFBSixHQUFXLElBRnBCLEVBR0wsSUFISyxDQUdBLFFBSEEsRUFHVSxJQUFJLElBQUosR0FBVyxJQUhyQixFQUlMLE1BSkssQ0FJRSxHQUpGLEVBS0wsSUFMSyxDQUtBLFdBTEEsRUFLYSxlQUFlLElBQWYsR0FBc0IsR0FBdEIsR0FBNEIsSUFBNUIsR0FBbUMsR0FMaEQsQ0FBVjs7QUFPQSxNQUFJLElBQUosQ0FBUyxXQUFUO0FBQ0EsTUFBSSxJQUFKLENBQVMsVUFBVDs7QUFFQSxXQUFTLE9BQVQsQ0FBaUIsR0FBakIsRUFBc0IsR0FBdEIsRUFBMkI7QUFDekIsa0JBQWMsR0FBZDtBQUNBLG9CQUFnQixHQUFoQjtBQUNEOztBQUVELFdBQVMsVUFBVCxDQUFvQixHQUFwQixFQUF5QixHQUF6QixFQUE4QjtBQUM1QixrQkFBYyxHQUFkO0FBQ0Esb0JBQWdCLEdBQWhCO0FBQ0Q7O0FBRUQsV0FBUyxJQUFULEdBQWdCO0FBQ2QsUUFBSSxNQUFNLEdBQUcsR0FBSCxDQUFPLGNBQWMsV0FBZCxHQUE0QixhQUFuQyxFQUFrRCxVQUFDLENBQUQ7QUFBQSxhQUFPLEVBQUUsS0FBVDtBQUFBLEtBQWxELENBQVY7QUFDQSxRQUFJLFFBQVEsWUFBWSxNQUF4QjtBQUNBLFFBQUksUUFBUSxLQUFLLEtBQUwsQ0FBVyxRQUFRLENBQW5CLENBQVo7O0FBR0EsTUFBRSxNQUFGLENBQVMsWUFBWSxHQUFaLENBQWdCLFVBQUMsQ0FBRDtBQUFBLGFBQU8sRUFBRSxLQUFUO0FBQUEsS0FBaEIsQ0FBVDtBQUNBLE1BQUUsTUFBRixDQUFTLENBQUMsQ0FBRCxFQUFLLE1BQU0sR0FBWCxDQUFUOztBQUVBO0FBQ0EsUUFBSSxTQUFKLENBQWMsR0FBZCxFQUFtQixNQUFuQjs7QUFFQTtBQUNBLFFBQUksTUFBSixDQUFXLEdBQVgsRUFDRyxJQURILENBQ1EsT0FEUixFQUNpQixRQURqQixFQUVHLElBRkgsQ0FFUSxLQUZSOztBQUlBLFFBQUksTUFBSixDQUFXLEdBQVgsRUFDRyxJQURILENBQ1EsT0FEUixFQUNpQixRQURqQixFQUVHLElBRkgsQ0FFUSxXQUZSLEVBRXFCLGlCQUFpQixDQUFqQixHQUFxQixHQUYxQyxFQUdHLElBSEgsQ0FHUSxLQUhSLEVBSUcsU0FKSCxDQUlhLEdBSmIsRUFLRyxLQUxILENBS1MsU0FMVCxFQUtvQixVQUFDLENBQUQsRUFBSSxDQUFKO0FBQUEsYUFBVSxJQUFJLEtBQUosSUFBYSxDQUFiLEdBQWlCLE1BQWpCLEdBQTBCLE9BQXBDO0FBQUEsS0FMcEI7O0FBT0E7QUFDQSxRQUFJLFdBQUosRUFBa0I7QUFDaEIsVUFBSSxPQUFPLElBQUksU0FBSixDQUFjLGVBQWQsRUFDUixJQURRLENBQ0gsV0FERyxFQUVSLEtBRlEsR0FHUixNQUhRLENBR0QsR0FIQyxFQUlSLElBSlEsQ0FJSCxPQUpHLEVBSU0sYUFKTixFQUtSLElBTFEsQ0FLSCxXQUxHLEVBS1UsVUFBVSxDQUFWLEVBQWEsQ0FBYixFQUFnQjtBQUFFLGVBQU8sZUFBZSxFQUFFLEVBQUUsS0FBSixDQUFmLEdBQTRCLE1BQW5DO0FBQTJDLE9BTHZFLENBQVg7O0FBT0EsV0FBSyxNQUFMLENBQVksTUFBWixFQUNHLElBREgsQ0FDUSxPQURSLEVBQ2lCLEVBQUUsU0FBRixFQURqQixFQUVHLElBRkgsQ0FFUSxRQUZSLEVBRWtCLFVBQUMsQ0FBRDtBQUFBLGVBQVEsSUFBSSxFQUFFLEVBQUUsS0FBSixDQUFaO0FBQUEsT0FGbEIsRUFHRyxJQUhILENBR1EsR0FIUixFQUdhLFVBQUMsQ0FBRDtBQUFBLGVBQU8sRUFBRSxFQUFFLEtBQUosQ0FBUDtBQUFBLE9BSGIsRUFJRyxFQUpILENBSU0sV0FKTixFQUltQixZQUFZLElBSi9CLEVBS0csRUFMSCxDQUtNLFVBTE4sRUFLa0IsWUFBWSxJQUw5QjtBQU1EOztBQUVELFFBQUcsYUFBSCxFQUFrQjtBQUNoQixVQUFJLGNBQWMsSUFBSSxTQUFKLENBQWMsV0FBZCxFQUNmLElBRGUsQ0FDVixhQURVLEVBRWYsS0FGZSxHQUdmLE1BSGUsQ0FHUixHQUhRLEVBSWYsSUFKZSxDQUlWLE9BSlUsRUFJRCxTQUpDLEVBS2YsSUFMZSxDQUtWLFdBTFUsRUFLRyxVQUFDLENBQUQsRUFBSSxDQUFKO0FBQUEsZUFBVSxnQkFBaUIsRUFBRSxFQUFFLEtBQUosSUFBZSxFQUFFLFNBQUYsS0FBZ0IsT0FBaEQsSUFBOEQsTUFBeEU7QUFBQSxPQUxILENBQWxCOztBQU9BLGtCQUFZLE1BQVosQ0FBbUIsTUFBbkIsRUFDRyxJQURILENBQ1EsT0FEUixFQUNpQixFQUFFLFNBQUYsS0FBZ0IsSUFEakMsRUFFRyxJQUZILENBRVEsUUFGUixFQUVrQixVQUFDLENBQUQ7QUFBQSxlQUFRLElBQUksRUFBRSxFQUFFLEtBQUosQ0FBWjtBQUFBLE9BRmxCLEVBR0csSUFISCxDQUdRLEdBSFIsRUFHYSxVQUFDLENBQUQ7QUFBQSxlQUFPLEVBQUUsRUFBRSxLQUFKLENBQVA7QUFBQSxPQUhiLEVBSUcsRUFKSCxDQUlNLFdBSk4sRUFJbUIsV0FBVyxJQUo5QixFQUtHLEVBTEgsQ0FLTSxVQUxOLEVBS2tCLFdBQVcsSUFMN0I7QUFNRDtBQUNGOztBQUVELFNBQU87QUFDTCxZQUFRLElBREg7QUFFTCxlQUFXLE9BRk47QUFHTCxrQkFBYztBQUhULEdBQVA7QUFLRDs7SUFHSyxLOzs7QUFDSixpQkFBWSxLQUFaLEVBQW1CO0FBQUE7O0FBQUEsOEdBQ1gsS0FEVzs7QUFHakIsVUFBSyxTQUFMLEdBQWlCLE1BQUssU0FBTCxDQUFlLElBQWYsT0FBakI7QUFDQSxVQUFLLFlBQUwsR0FBb0IsTUFBSyxZQUFMLENBQWtCLElBQWxCLE9BQXBCO0FBQ0EsVUFBSyxJQUFMLEdBQVk7QUFDVixnQkFBVSxJQURBO0FBRVYsaUJBQVc7QUFGRCxLQUFaO0FBTGlCO0FBU2xCOzs7O3dDQUVtQjtBQUNsQixXQUFLLEtBQUwsR0FBYSxJQUFJLEtBQUosQ0FBVSxTQUFTLGNBQVQsQ0FBd0IsT0FBeEIsQ0FBVixFQUE0QyxLQUFLLEtBQUwsQ0FBVyxhQUF2RCxFQUFzRSxLQUFLLEtBQUwsQ0FBVyxZQUFqRixDQUFiO0FBQ0EsV0FBSyxTQUFMLENBQWUsS0FBSyxLQUFMLENBQVcsTUFBMUI7QUFDRDs7OzhDQUV5QixRLEVBQVU7QUFDbEMsVUFBRyxLQUFLLEtBQUwsQ0FBVyxNQUFYLElBQXFCLFNBQVMsTUFBakMsRUFBeUM7QUFDdkMsYUFBSyxTQUFMLENBQWUsU0FBUyxNQUF4QjtBQUNEOztBQUVELFdBQUssS0FBTCxDQUFXLFVBQVgsQ0FBc0IsU0FBUyxhQUEvQixFQUE4QyxTQUFTLFlBQXZEO0FBQ0EsV0FBSyxLQUFMLENBQVcsSUFBWDtBQUNEOzs7NENBRXVCO0FBQ3RCLGFBQU8sS0FBUDtBQUNEOzs7bUNBRWM7O0FBRWIsVUFBRyxLQUFLLElBQUwsQ0FBVSxRQUFWLElBQXNCLEtBQUssSUFBTCxDQUFVLFNBQW5DLEVBQThDO0FBQzVDLGFBQUssZ0JBQUwsQ0FBc0IsS0FBdEIsQ0FBNEIsT0FBNUIsR0FBc0MsTUFBdEM7QUFDQSxhQUFLLEtBQUwsQ0FBVyxPQUFYLENBQW1CLEtBQUssSUFBTCxDQUFVLFNBQTdCLEVBQXdDLEtBQUssSUFBTCxDQUFVLFFBQWxEO0FBQ0EsYUFBSyxLQUFMLENBQVcsSUFBWDtBQUNEO0FBQ0Y7Ozs4QkFFUyxNLEVBQVE7QUFBQTs7QUFDaEIsVUFBTSxTQUFTLEtBQUssS0FBTCxDQUFZLENBQUMsSUFBSSxJQUFKLEVBQUYsR0FBaUIsSUFBNUIsQ0FBZjtBQUNBLFVBQU0sUUFBUSxTQUFXLFNBQVMsWUFBbEM7QUFDQSxVQUFNLFFBQVEsU0FBUyxFQUFULEdBQWMsT0FBZCxHQUF3QixLQUF0QztBQUNBLFdBQUssZ0JBQUwsQ0FBc0IsS0FBdEIsQ0FBNEIsT0FBNUIsR0FBc0MsRUFBdEM7O0FBRUEsdUJBQ0csT0FESCw0QkFDb0MsS0FEcEMsZ0JBQ29ELE1BRHBELGVBQ29FLEtBRHBFLEVBRUcsSUFGSCxDQUVRLFVBQUMsQ0FBRCxFQUFPO0FBQ1gsZUFBSyxJQUFMLENBQVUsU0FBVixHQUFzQixDQUF0QjtBQUNBLGVBQU8scUJBQVAsQ0FBNkIsT0FBSyxZQUFsQztBQUNELE9BTEg7O0FBT0EsdUJBQ0csT0FESCwyQkFDbUMsS0FEbkMsZ0JBQ21ELE1BRG5ELGVBQ21FLEtBRG5FLEVBRUcsSUFGSCxDQUVRLFVBQUMsQ0FBRCxFQUFPO0FBQ1gsZUFBSyxJQUFMLENBQVUsUUFBVixHQUFxQixDQUFyQjtBQUNBLGVBQU8scUJBQVAsQ0FBNkIsT0FBSyxZQUFsQztBQUNELE9BTEg7QUFNRDs7OzZCQUVRO0FBQUE7O0FBQ1AsYUFDRTtBQUFBO0FBQUE7QUFDRTtBQUFBO0FBQUEsWUFBSyxTQUFNLGlCQUFYLEVBQTZCLEtBQUssYUFBQyxFQUFELEVBQVE7QUFBRSxxQkFBSyxnQkFBTCxHQUF3QixFQUF4QjtBQUE0QixhQUF4RTtBQUEwRTtBQUExRSxTQURGO0FBRUUsZ0NBQUssSUFBRyxPQUFSO0FBRkYsT0FERjtBQU1EOzs7Ozs7a0JBR1ksSzs7O0FDN0xmOzs7Ozs7OztBQUVBOztBQUNBOzs7Ozs7Ozs7Ozs7SUFFTSxXOzs7QUFFSix1QkFBWSxLQUFaLEVBQW1CO0FBQUE7O0FBQUEsMEhBQ1gsS0FEVzs7QUFFakIsVUFBSyxLQUFMLEdBQWE7QUFDWCxxQkFBZSxJQURKO0FBRVgsb0JBQWM7QUFGSCxLQUFiO0FBRmlCO0FBTWxCOzs7OzZCQUVRO0FBQUE7O0FBQ1AsYUFDRTtBQUFBO0FBQUEsVUFBSyxTQUFNLE9BQVg7QUFDRTtBQUFBO0FBQUEsWUFBSyxTQUFNLFlBQVg7QUFDRTtBQUFBO0FBQUEsY0FBTyxTQUFNLDJCQUFiO0FBQXlDLHNDQUFPLE1BQUssVUFBWixFQUF1QixTQUFTLEtBQUssS0FBTCxDQUFXLGFBQTNDLEVBQTBELFVBQVUsa0JBQUMsQ0FBRDtBQUFBLHVCQUFPLE9BQUssUUFBTCxDQUFjLEVBQUUsZUFBZSxFQUFFLE1BQUYsQ0FBUyxPQUExQixFQUFkLENBQVA7QUFBQSxlQUFwRSxHQUF6QztBQUFBO0FBQUEsV0FERjtBQUVFO0FBQUE7QUFBQSxjQUFPLFNBQU0sUUFBYjtBQUFzQixzQ0FBTyxNQUFLLFVBQVosRUFBdUIsU0FBUyxLQUFLLEtBQUwsQ0FBVyxZQUEzQyxFQUF5RCxVQUFVLGtCQUFDLENBQUQ7QUFBQSx1QkFBTyxPQUFLLFFBQUwsQ0FBYyxFQUFFLGNBQWMsRUFBRSxNQUFGLENBQVMsT0FBekIsRUFBZCxDQUFQO0FBQUEsZUFBbkUsR0FBdEI7QUFBQTtBQUFBO0FBRkYsU0FERjtBQUtFLDBDQUFPLFFBQVEsS0FBSyxLQUFMLENBQVcsTUFBMUIsRUFBa0MsZUFBZSxLQUFLLEtBQUwsQ0FBVyxhQUE1RCxFQUEyRSxjQUFjLEtBQUssS0FBTCxDQUFXLFlBQXBHO0FBTEYsT0FERjtBQVNEOzs7Ozs7a0JBR1ksVzs7O0FDNUJmOzs7Ozs7OztBQUVBOztBQUNBOzs7Ozs7Ozs7Ozs7SUFFTSxTOzs7Ozs7Ozs7Ozs2QkFDSztBQUNQLFVBQU0sZUFBZSxLQUFLLEtBQUwsQ0FBVyxVQUFYLEdBQXdCLHlDQUFjLFdBQVcsS0FBSyxLQUFMLENBQVcsUUFBcEMsR0FBeEIsR0FBMkUsRUFBaEc7O0FBRUEsYUFDRTtBQUFBO0FBQUEsVUFBUSxTQUFNLGVBQWQ7QUFDRTtBQUFBO0FBQUEsWUFBSyxTQUFNLFdBQVg7QUFDRTtBQUFBO0FBQUEsY0FBSSxTQUFNLGlCQUFWO0FBQUE7QUFBZ0M7QUFBQTtBQUFBLGdCQUFPLFNBQU0sVUFBYjtBQUFBO0FBQUE7QUFBaEMsV0FERjtBQUVFO0FBQUE7QUFBQSxjQUFLLFNBQU0sWUFBWDtBQUNLO0FBREw7QUFGRjtBQURGLE9BREY7QUFTQTs7Ozs7O2tCQUdXLFM7OztBQ3JCZjs7Ozs7Ozs7QUFFQTs7QUFDQTs7OztBQUNBOzs7Ozs7Ozs7Ozs7SUFFTSxTOzs7QUFFSixxQkFBWSxLQUFaLEVBQW1CO0FBQUE7O0FBQUEsc0hBQ1gsS0FEVzs7QUFFakIsVUFBSyxZQUFMLEdBQW9CLE1BQUssWUFBTCxDQUFrQixJQUFsQixPQUFwQjtBQUNBLFVBQUssS0FBTCxHQUFhO0FBQ1gsYUFBTyxFQURJO0FBRVgsZ0JBQVUsRUFGQztBQUdYLGVBQVM7QUFIRSxLQUFiO0FBSGlCO0FBUWxCOzs7O2lDQUVZLEMsRUFBRztBQUFBOztBQUNkLFFBQUUsY0FBRjs7QUFFQSx1QkFBTyxPQUFQLENBQWUsU0FBZixFQUEwQjtBQUN4QixnQkFBUSxNQURnQjtBQUV4QixjQUFNO0FBQ0osaUJBQU8sS0FBSyxLQUFMLENBQVcsS0FEZDtBQUVKLG9CQUFVLEtBQUssS0FBTCxDQUFXO0FBRmpCO0FBRmtCLE9BQTFCLEVBTUcsSUFOSCxDQU1RLFVBQUMsQ0FBRCxFQUFPO0FBQ1gsZUFBSyxLQUFMLENBQVcsU0FBWDtBQUNILE9BUkQsRUFRRyxLQVJILENBUVMsVUFBQyxDQUFELEVBQU87QUFDZCxlQUFLLFFBQUwsQ0FBYztBQUNaLG1CQUFTLEVBQUUsT0FEQztBQUVaLG9CQUFVO0FBRkUsU0FBZDtBQUtELE9BZEQ7QUFlRDs7OzZCQUVRO0FBQ1AsYUFDRTtBQUFBO0FBQUEsVUFBSyxTQUFNLE9BQVg7QUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBLFNBREY7QUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBLFNBRkY7QUFHRTtBQUFBO0FBQUEsWUFBTSxRQUFPLE1BQWIsRUFBb0IsVUFBVSxLQUFLLFlBQW5DO0FBQ0U7QUFBQTtBQUFBLGNBQUssU0FBTSxjQUFYO0FBQ0U7QUFBQTtBQUFBO0FBQUE7QUFBQSxhQURGO0FBRUUsc0NBQU8sTUFBSyxPQUFaLEVBQW9CLE1BQUssT0FBekIsRUFBaUMsYUFBWSxlQUE3QyxFQUE2RCxPQUFPLEtBQUssS0FBTCxDQUFXLEtBQS9FLEVBQXNGLFVBQVUsS0FBSyxTQUFMLENBQWUsT0FBZixDQUFoRyxFQUF5SCxVQUFTLFVBQWxJO0FBRkYsV0FERjtBQUtFO0FBQUE7QUFBQSxjQUFLLFNBQU0sY0FBWDtBQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUEsYUFERjtBQUVFLHNDQUFPLE1BQUssVUFBWixFQUF1QixNQUFLLFVBQTVCLEVBQXVDLGFBQVksWUFBbkQsRUFBZ0UsT0FBTyxLQUFLLEtBQUwsQ0FBVyxRQUFsRixFQUE0RixVQUFVLEtBQUssU0FBTCxDQUFlLFVBQWYsQ0FBdEcsRUFBa0ksVUFBUyxVQUEzSTtBQUZGLFdBTEY7QUFTRTtBQUFBO0FBQUEsY0FBSyxTQUFNLGNBQVg7QUFDRSxzQ0FBTyxNQUFLLFFBQVosRUFBcUIsT0FBTSxTQUEzQjtBQURGO0FBVEYsU0FIRjtBQWdCRSxpREFBYyxTQUFTLEtBQUssS0FBTCxDQUFXLE9BQWxDLEVBQTJDLE1BQUssRUFBaEQ7QUFoQkYsT0FERjtBQXFCRDs7Ozs7O2tCQUdZLFM7OztBQy9EZjs7Ozs7Ozs7QUFFQTs7QUFDQTs7Ozs7Ozs7Ozs7O0lBRU0sWTs7O0FBRUosd0JBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLDRIQUNYLEtBRFc7O0FBRWpCLFVBQUssWUFBTCxHQUFvQixNQUFLLFlBQUwsQ0FBa0IsSUFBbEIsT0FBcEI7QUFGaUI7QUFHbEI7Ozs7aUNBRVksQyxFQUFHO0FBQUE7O0FBQ2QsUUFBRSxjQUFGOztBQUVBLHVCQUFPLE9BQVAsQ0FBZSxTQUFmLEVBQTBCO0FBQ3hCLGdCQUFRO0FBRGdCLE9BQTFCLEVBRUcsSUFGSCxDQUVRLFVBQUMsQ0FBRCxFQUFPO0FBQUUsZUFBSyxLQUFMLENBQVcsU0FBWDtBQUF3QixPQUZ6QztBQUdEOzs7NkJBRVE7QUFDUCxhQUNFO0FBQUE7QUFBQSxVQUFHLE1BQUssR0FBUixFQUFZLFNBQVMsS0FBSyxZQUExQjtBQUFBO0FBQUEsT0FERjtBQUdEOzs7Ozs7a0JBR1ksWTs7O0FDM0JmOzs7Ozs7OztBQUVBOzs7Ozs7OztJQUVNLFk7OztBQUNKLHdCQUFZLEtBQVosRUFBbUI7QUFBQTs7QUFBQSw0SEFDWCxLQURXOztBQUdqQixVQUFLLEtBQUwsR0FBYTtBQUNYLGVBQVMsTUFBTSxPQURKO0FBRVgsWUFBTSxNQUFNLElBQU4sSUFBYztBQUZULEtBQWI7QUFJQSxVQUFLLE9BQUwsR0FBZSxDQUFmO0FBUGlCO0FBUWxCOzs7O21DQUVjO0FBQ2IsV0FBSyxRQUFMLENBQWMsRUFBRSxTQUFTLEVBQVgsRUFBZDtBQUNEOzs7OENBRXlCLFEsRUFBVTtBQUNsQyxVQUFHLFNBQVMsT0FBVCxJQUFvQixLQUFLLEtBQUwsQ0FBVyxPQUFsQyxFQUEyQztBQUN6QyxhQUFLLFFBQUwsQ0FBYyxFQUFFLFNBQVMsU0FBUyxPQUFwQixFQUE2QixNQUFNLFNBQVMsSUFBVCxJQUFpQixPQUFwRCxFQUFkO0FBQ0EsZUFBTyxZQUFQLENBQW9CLEtBQUssT0FBekI7QUFDQSxhQUFLLE9BQUwsR0FBZSxPQUFPLFVBQVAsQ0FBa0IsS0FBSyxZQUFMLENBQWtCLElBQWxCLENBQXVCLElBQXZCLENBQWxCLEVBQWdELElBQWhELENBQWY7QUFDRDtBQUNGOzs7NkJBRVE7QUFDUCxVQUFHLEtBQUssS0FBTCxDQUFXLE9BQVgsS0FBdUIsRUFBMUIsRUFBOEI7QUFDNUIsZUFBTyxFQUFQO0FBQ0Q7O0FBRUQsYUFDRTtBQUFBO0FBQUEsVUFBSyx1QkFBTDtBQUNFO0FBQUE7QUFBQSxZQUFLLDJCQUF1QixLQUFLLEtBQUwsQ0FBVyxJQUF2QztBQUNHLGVBQUssS0FBTCxDQUFXO0FBRGQ7QUFERixPQURGO0FBTUE7Ozs7OztrQkFHVyxZOzs7QUN6Q2Y7Ozs7Ozs7O0FBRUE7O0FBQ0E7O0lBQVksTzs7QUFDWjs7Ozs7Ozs7Ozs7Ozs7QUFFQSxJQUFNLGVBQWUsS0FBSyxFQUFMLEdBQVUsRUFBL0I7O0lBRU0sUzs7O0FBRUoscUJBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLHNIQUNYLEtBRFc7O0FBR2pCLFVBQUssS0FBTCxHQUFhO0FBQ1gsZUFBUyxFQURFO0FBRVgsZUFBUztBQUZFLEtBQWI7QUFJQSxVQUFLLFlBQUwsR0FBb0IsTUFBSyxZQUFMLENBQWtCLElBQWxCLE9BQXBCO0FBUGlCO0FBUWxCOzs7O3dDQUVtQjtBQUNsQixXQUFLLFlBQUwsQ0FBa0IsS0FBSyxLQUFMLENBQVcsTUFBN0I7QUFDRDs7OzhDQUV5QixRLEVBQVU7QUFDbEMsVUFBRyxLQUFLLEtBQUwsQ0FBVyxNQUFYLElBQXFCLFNBQVMsTUFBakMsRUFBeUM7QUFDdkMsYUFBSyxZQUFMLENBQWtCLFNBQVMsTUFBM0I7QUFDRDtBQUNGOzs7aUNBRVksTSxFQUFRO0FBQUE7O0FBQ25CLFVBQU0sU0FBUyxLQUFLLEtBQUwsQ0FBWSxDQUFDLElBQUksSUFBSixFQUFGLEdBQWlCLElBQTVCLENBQWY7QUFDQSxVQUFNLFFBQVEsU0FBVyxTQUFTLFlBQWxDO0FBQ0EsV0FBSyxRQUFMLENBQWMsRUFBRSxTQUFTLElBQVgsRUFBZDs7QUFFQSx1QkFBTyxPQUFQLHVCQUFtQyxNQUFuQyxlQUFtRCxLQUFuRCxFQUNDLElBREQsQ0FDTSxVQUFDLENBQUQsRUFBTztBQUFFLGVBQUssUUFBTCxDQUFjLEVBQUUsU0FBUyxLQUFYLEVBQWtCLFNBQVMsQ0FBM0IsRUFBZDtBQUE4QyxPQUQ3RCxFQUVDLEtBRkQsQ0FFTyxVQUFDLENBQUQsRUFBTztBQUFFLGdCQUFRLEdBQVIsQ0FBWSxDQUFaO0FBQWdCLE9BRmhDO0FBR0Q7Ozs2QkFFUTtBQUNQLFVBQU0saUJBQWlCLEtBQUssS0FBTCxDQUFXLE9BQVgsR0FBcUI7QUFBQTtBQUFBLFVBQUssU0FBTSxpQkFBWDtBQUE2QjtBQUE3QixPQUFyQixHQUFzRSxFQUE3RjtBQUNBLFVBQU0sWUFBWSxLQUFLLEtBQUwsQ0FBVyxPQUFYLENBQW1CLEdBQW5CLENBQXdCLFVBQUMsQ0FBRCxFQUFJLENBQUo7QUFBQSxlQUN4QztBQUFBO0FBQUE7QUFDRTtBQUFBO0FBQUEsY0FBSSxTQUFNLE9BQVY7QUFBbUIsZ0JBQUU7QUFBckIsV0FERjtBQUVFO0FBQUE7QUFBQTtBQUFJO0FBQUE7QUFBQSxnQkFBRyxNQUFNLE9BQU8sRUFBRSxRQUFULEdBQW9CLEVBQUUsSUFBL0I7QUFBc0MsZ0JBQUUsSUFBRixDQUFPLFNBQVAsQ0FBaUIsQ0FBakIsRUFBb0IsRUFBcEIsQ0FBdEM7QUFBK0QsZ0JBQUUsSUFBRixDQUFPLE1BQVAsR0FBZ0IsRUFBaEIsR0FBcUIsSUFBckIsR0FBNEI7QUFBM0Y7QUFBSixXQUZGO0FBR0U7QUFBQTtBQUFBO0FBQUssb0JBQVEsZUFBUixDQUF3QixFQUFFLEtBQTFCO0FBQUwsV0FIRjtBQUlFO0FBQUE7QUFBQTtBQUFLLG9CQUFRLGVBQVIsQ0FBd0IsRUFBRSxXQUExQjtBQUFMO0FBSkYsU0FEd0M7QUFBQSxPQUF4QixDQUFsQjs7QUFTQSxhQUNFO0FBQUE7QUFBQSxVQUFLLFNBQU0sT0FBWDtBQUNHLHNCQURIO0FBRUU7QUFBQTtBQUFBO0FBQUE7QUFBQSxTQUZGO0FBR0U7QUFBQTtBQUFBLFlBQU8sU0FBTSxpQkFBYjtBQUNFO0FBQUE7QUFBQTtBQUNFO0FBQUE7QUFBQTtBQUNFO0FBQUE7QUFBQTtBQUFBO0FBQUEsZUFERjtBQUVFO0FBQUE7QUFBQTtBQUFBO0FBQUEsZUFGRjtBQUdFO0FBQUE7QUFBQTtBQUFBO0FBQUEsZUFIRjtBQUlFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFKRjtBQURGLFdBREY7QUFTRTtBQUFBO0FBQUE7QUFBUTtBQUFSO0FBVEY7QUFIRixPQURGO0FBaUJEOzs7Ozs7a0JBR1ksUzs7O0FDdkVmOzs7Ozs7OztBQUVBOztBQUNBOzs7Ozs7Ozs7Ozs7SUFFTSxROzs7QUFFSixvQkFBWSxLQUFaLEVBQW1CO0FBQUE7O0FBQUEsb0hBQ1gsS0FEVzs7QUFHakIsVUFBSyxLQUFMLEdBQWE7QUFDWCxhQUFPO0FBREksS0FBYjtBQUdBLFVBQUssU0FBTCxHQUFpQixNQUFLLFNBQUwsQ0FBZSxJQUFmLE9BQWpCO0FBQ0EsVUFBSyxTQUFMO0FBQ0EsV0FBTyxXQUFQLENBQW1CLE1BQUssU0FBeEIsRUFBbUMsS0FBbkM7QUFSaUI7QUFTbEI7Ozs7Z0NBRVc7QUFBQTs7QUFDVix1QkFBTyxPQUFQLDRCQUNHLElBREgsQ0FDUSxVQUFDLENBQUQsRUFBTztBQUFFLGVBQUssUUFBTCxDQUFjLEVBQUUsT0FBTyxDQUFULEVBQWQ7QUFBNEIsT0FEN0M7QUFFRDs7OzZCQUVRO0FBQ1AsVUFBSSxXQUFXLEtBQUssS0FBTCxDQUFXLEtBQVgsSUFBb0IsQ0FBcEIsR0FBd0IsU0FBeEIsR0FBb0MsVUFBbkQ7QUFDQSxhQUNFO0FBQUE7QUFBQSxVQUFLLFNBQU0sbUJBQVg7QUFDRTtBQUFBO0FBQUEsWUFBTSxTQUFNLE9BQVo7QUFBcUIsZUFBSyxLQUFMLENBQVc7QUFBaEMsU0FERjtBQUFBO0FBQ2dEO0FBQUE7QUFBQTtBQUFPLGtCQUFQO0FBQUE7QUFBQTtBQURoRCxPQURGO0FBS0Q7Ozs7OztrQkFHWSxROzs7QUNqQ2Y7Ozs7Ozs7O0FBRUE7O0FBQ0E7O0lBQVksTzs7QUFDWjs7Ozs7Ozs7Ozs7Ozs7QUFDQSxJQUFNLGVBQWUsS0FBSyxFQUFMLEdBQVUsRUFBL0I7O0lBRU0sSzs7O0FBRUosaUJBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLDhHQUNYLEtBRFc7O0FBR2pCLFVBQUssS0FBTCxHQUFhO0FBQ1gsZUFBUyxFQURFO0FBRVgsYUFBTyxDQUZJO0FBR1gsZUFBUztBQUhFLEtBQWI7O0FBTUEsVUFBSyxZQUFMLEdBQW9CLE1BQU0sT0FBTixDQUFjLEdBQWQsQ0FBa0I7QUFBQSxhQUFXO0FBQUE7QUFBQTtBQUFLO0FBQUwsT0FBWDtBQUFBLEtBQWxCLENBQXBCO0FBQ0EsVUFBSyxZQUFMLEdBQW9CLE1BQUssWUFBTCxDQUFrQixJQUFsQixPQUFwQjtBQUNBLFVBQUssaUJBQUwsR0FBeUIsTUFBSyxpQkFBTCxDQUF1QixJQUF2QixPQUF6QjtBQVhpQjtBQVlsQjs7Ozt3Q0FFbUI7QUFDaEIsV0FBSyxZQUFMLENBQWtCLEtBQUssS0FBTCxDQUFXLE1BQTdCLEVBQXFDLEtBQUssS0FBTCxDQUFXLEtBQWhEO0FBQ0g7Ozs4QkFFUyxDLEVBQUc7QUFDWCxVQUFJLEtBQUssS0FBTCxDQUFXLFNBQWYsRUFBMkI7QUFDekIsZUFBTyxLQUFLLEtBQUwsQ0FBVyxTQUFYLENBQXFCLENBQXJCLENBQVA7QUFDRDs7QUFFRCxhQUNFO0FBQUE7QUFBQTtBQUFLLFVBQUUsS0FBRixDQUFRLFNBQVIsQ0FBa0IsQ0FBbEIsRUFBcUIsRUFBckI7QUFBTCxPQURGO0FBR0Q7Ozs4Q0FFeUIsUSxFQUFVO0FBQ2xDLFVBQUcsS0FBSyxLQUFMLENBQVcsTUFBWCxJQUFxQixTQUFTLE1BQWpDLEVBQXlDO0FBQ3ZDLGFBQUssWUFBTCxDQUFrQixTQUFTLE1BQTNCLEVBQW1DLEtBQUssS0FBTCxDQUFXLEtBQTlDO0FBQ0Q7QUFDRjs7O3NDQUVpQixDLEVBQUc7QUFDbkIsV0FBSyxRQUFMLENBQWMsRUFBRSxPQUFPLFNBQVMsRUFBRSxNQUFGLENBQVMsS0FBbEIsQ0FBVCxFQUFkO0FBQ0EsV0FBSyxZQUFMLENBQWtCLEtBQUssS0FBTCxDQUFXLE1BQTdCLEVBQXFDLEtBQUssS0FBTCxDQUFXLEtBQWhEO0FBQ0Q7OztpQ0FFWSxNLEVBQVEsSyxFQUFPO0FBQUE7O0FBQzFCLFdBQUssUUFBTCxDQUFjLEVBQUUsU0FBUyxJQUFYLEVBQWQ7QUFDQSxVQUFNLFNBQVMsS0FBSyxLQUFMLENBQVksQ0FBQyxJQUFJLElBQUosRUFBRixHQUFpQixJQUE1QixDQUFmO0FBQ0EsVUFBTSxRQUFRLFNBQVcsU0FBUyxZQUFsQzs7QUFFQSx1QkFBTyxPQUFQLENBQWtCLEtBQUssS0FBTCxDQUFXLFFBQTdCLGdCQUFnRCxNQUFoRCxlQUFnRSxLQUFoRSxlQUErRSxLQUEvRSxFQUNHLElBREgsQ0FDUSxVQUFDLENBQUQsRUFBTztBQUNYLGVBQUssUUFBTCxDQUFjLEVBQUUsU0FBUyxLQUFYLEVBQWtCLFNBQVMsQ0FBM0IsRUFBZDtBQUNBLE9BSEosRUFHTSxLQUhOLENBR1ksVUFBQyxDQUFELEVBQU87QUFBRSxnQkFBUSxHQUFSLENBQVksQ0FBWjtBQUFnQixPQUhyQztBQUlEOzs7NkJBRVE7QUFBQTs7QUFDUCxVQUFNLFlBQVksS0FBSyxLQUFMLENBQVcsT0FBWCxDQUFtQixNQUFuQixHQUE0QixDQUE1QixHQUFnQyxLQUFLLEtBQUwsQ0FBVyxPQUFYLENBQW1CLEdBQW5CLENBQXVCLFVBQUMsQ0FBRCxFQUFJLENBQUo7QUFBQSxlQUN2RTtBQUFBO0FBQUE7QUFDRTtBQUFBO0FBQUEsY0FBSSxTQUFNLE9BQVY7QUFBbUIsZ0JBQUU7QUFBckIsV0FERjtBQUVHLGlCQUFLLFNBQUwsQ0FBZSxDQUFmLENBRkg7QUFHRTtBQUFBO0FBQUE7QUFBSyxvQkFBUSxlQUFSLENBQXdCLEVBQUUsS0FBMUI7QUFBTCxXQUhGO0FBSUU7QUFBQTtBQUFBO0FBQUssaUJBQUssS0FBTCxDQUFXLEVBQUUsZUFBYixDQUFMO0FBQUE7QUFBQTtBQUpGLFNBRHVFO0FBQUEsT0FBdkIsQ0FBaEMsR0FPZDtBQUFBO0FBQUE7QUFBSTtBQUFBO0FBQUEsWUFBSSxTQUFRLEdBQVosRUFBZ0IsU0FBTSxRQUF0QjtBQUFBO0FBQUE7QUFBSixPQVBKOztBQVNBLFVBQU0saUJBQWlCLEtBQUssS0FBTCxDQUFXLE9BQVgsR0FBcUI7QUFBQTtBQUFBLFVBQUssU0FBTSxpQkFBWDtBQUE2QjtBQUE3QixPQUFyQixHQUFzRSxFQUE3Rjs7QUFFQSxhQUNFO0FBQUE7QUFBQSxVQUFLLFNBQU0sT0FBWDtBQUNHLHNCQURIO0FBRUU7QUFBQTtBQUFBLFlBQUssU0FBTSxVQUFYO0FBQ0U7QUFBQTtBQUFBLGNBQUksU0FBTSxXQUFWO0FBQXVCLGlCQUFLLEtBQUwsQ0FBVztBQUFsQyxXQURGO0FBRUU7QUFBQTtBQUFBLGNBQUssU0FBTSxZQUFYO0FBQ0U7QUFBQTtBQUFBLGdCQUFRLFVBQVUsS0FBSyxpQkFBdkI7QUFDRTtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBREY7QUFFRTtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBRkY7QUFHRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBSEY7QUFERjtBQUZGLFNBRkY7QUFZRTtBQUFBO0FBQUE7QUFDRTtBQUFBO0FBQUE7QUFDRTtBQUFBO0FBQUE7QUFBSyxtQkFBSztBQUFWO0FBREYsV0FERjtBQUlFO0FBQUE7QUFBQTtBQUNHO0FBREg7QUFKRjtBQVpGLE9BREY7QUF1QkQ7Ozs7OztrQkFHWSxLOzs7QUNqR2Y7Ozs7O0FBRUEsSUFBSSxTQUFTLEVBQWI7QUFDQSxPQUFPLE9BQVAsR0FBaUIsVUFBUyxRQUFULEVBQW1CLElBQW5CLEVBQXlCO0FBQ3hDLFNBQU8sUUFBUSxFQUFmO0FBQ0EsT0FBSyxXQUFMLEdBQW1CLGFBQW5CO0FBQ0EsT0FBSyxPQUFMLEdBQWUsS0FBSyxPQUFMLElBQWdCLEVBQS9CO0FBQ0EsT0FBSyxPQUFMLENBQWEsUUFBYixJQUF5QixrQkFBekI7O0FBRUEsTUFBSSxLQUFLLE1BQUwsSUFBZSxLQUFLLE1BQUwsS0FBZ0IsTUFBbkMsRUFBMkM7QUFDekMsU0FBSyxPQUFMLENBQWEsY0FBYixJQUErQixrQkFBL0I7O0FBRUEsUUFBRyxLQUFLLElBQVIsRUFBYztBQUNaLFVBQUksT0FBTyxLQUFLLElBQVosS0FBc0IsUUFBMUIsRUFBb0M7QUFDbEMsYUFBSyxJQUFMLEdBQVksS0FBSyxTQUFMLENBQWUsS0FBSyxJQUFwQixDQUFaO0FBQ0Q7QUFDRCxXQUFLLElBQUwsR0FBWSxLQUFLLElBQWpCO0FBQ0EsYUFBTyxLQUFLLElBQVo7QUFDRDtBQUNGOztBQUVELFNBQU8sZ0JBQWMsUUFBZCxFQUEwQixJQUExQixFQUNKLElBREksQ0FDQyxTQURELEVBRUosSUFGSSxDQUVDLFNBRkQsQ0FBUDtBQUdELENBckJEOztBQXVCQSxTQUFTLFNBQVQsQ0FBbUIsQ0FBbkIsRUFBc0I7QUFDcEIsU0FBTyxFQUFFLElBQUYsRUFBUDtBQUNEOztBQUVELFNBQVMsU0FBVCxDQUFtQixDQUFuQixFQUFzQjtBQUNwQixNQUFHLEVBQUUsS0FBTCxFQUFZO0FBQ1YsVUFBTSxJQUFJLEtBQUosQ0FBVSxFQUFFLEtBQVosQ0FBTjtBQUNEOztBQUVELFNBQU8sRUFBRSxJQUFUO0FBQ0Q7O2tCQUVjLE07Ozs7Ozs7O0FDdENmLFNBQVMsZUFBVCxDQUF5QixJQUF6QixFQUErQjtBQUM5QixTQUFRLEVBQVI7O0FBRUMsS0FBRyxLQUFLLE1BQUwsR0FBYyxDQUFqQixFQUFxQjtBQUNuQixTQUFPLElBQVA7QUFDRDs7QUFFRCxLQUFJLElBQUksS0FBSyxLQUFMLENBQVcsR0FBWCxDQUFSO0FBQ0QsS0FBSSxLQUFLLEVBQUUsQ0FBRixDQUFUO0FBQ0EsS0FBSSxLQUFLLEVBQUUsTUFBRixHQUFXLENBQVgsR0FBZSxNQUFNLEVBQUUsQ0FBRixDQUFyQixHQUE0QixFQUFyQztBQUNBLEtBQUksTUFBTSxjQUFWO0FBQ0EsUUFBTyxJQUFJLElBQUosQ0FBUyxFQUFULENBQVAsRUFBcUI7QUFDcEIsT0FBSyxHQUFHLE9BQUgsQ0FBVyxHQUFYLEVBQWdCLE9BQU8sR0FBUCxHQUFhLElBQTdCLENBQUw7QUFDQTtBQUNELFFBQU8sS0FBSyxFQUFaO0FBQ0E7O1FBRVEsZSxHQUFBLGU7OztBQ2pCVDs7Ozs7Ozs7QUFFQTs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7Ozs7Ozs7Ozs7O0FBRUEsU0FBUyxnQkFBVCxDQUEwQixDQUExQixFQUE2QjtBQUMzQixJQUFFLE1BQUYsQ0FBUyxVQUFULENBQW9CLFdBQXBCLENBQWdDLEVBQUUsTUFBbEM7QUFDRDs7QUFFRCxTQUFTLGtCQUFULENBQTRCLENBQTVCLEVBQStCO0FBQzdCLE1BQU0sTUFBTSwrQkFBOEIsRUFBRSxLQUFGLENBQVEsV0FBUixFQUE5QixHQUFxRCxNQUFqRTs7QUFFQSxTQUNFO0FBQUE7QUFBQTtBQUNHLE1BQUUsS0FETDtBQUVFLDRCQUFLLFFBQU8sSUFBWixFQUFpQixLQUFLLEdBQXRCLEVBQTJCLFNBQU0sWUFBakMsRUFBOEMsU0FBUyxnQkFBdkQ7QUFGRixHQURGO0FBTUQ7O0lBRUssUzs7O0FBQ0oscUJBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLHNIQUNYLEtBRFc7O0FBR2pCLFVBQUssS0FBTCxHQUFhO0FBQ1gsY0FBUSxTQUFTLE9BQU8sUUFBUCxDQUFnQixJQUFoQixDQUFxQixTQUFyQixDQUErQixDQUEvQixDQUFULEtBQStDO0FBRDVDLEtBQWI7O0FBSUEsVUFBSyxjQUFMLEdBQXNCLE1BQUssY0FBTCxDQUFvQixJQUFwQixPQUF0QjtBQVBpQjtBQVFsQjs7OzttQ0FFYyxDLEVBQUc7QUFDaEIsV0FBSyxRQUFMLENBQWMsRUFBRSxRQUFRLENBQVYsRUFBZDtBQUNBLGFBQU8sT0FBUCxDQUFlLFlBQWYsQ0FBNEIsS0FBSyxLQUFqQyxFQUF3QyxJQUF4QyxTQUFtRCxDQUFuRDtBQUNEOzs7NkJBRVE7QUFDUCxhQUNBO0FBQUE7QUFBQTtBQUNFLDhDQUFXLFlBQVksSUFBdkIsRUFBNkIsVUFBVSxLQUFLLEtBQUwsQ0FBVyxRQUFsRCxHQURGO0FBRUU7QUFBQTtBQUFBLFlBQUssU0FBTSxXQUFYO0FBQ0Usa0RBREY7QUFFRTtBQUFBO0FBQUEsY0FBSyxTQUFNLE9BQVg7QUFDRSxtREFBWSxRQUFRLEtBQUssS0FBTCxDQUFXLE1BQS9CLEVBQXVDLFVBQVUsS0FBSyxjQUF0RDtBQURGLFdBRkY7QUFLRTtBQUFBO0FBQUEsY0FBSyxTQUFNLEtBQVg7QUFDRTtBQUFBO0FBQUEsZ0JBQUssU0FBTSxPQUFYO0FBQ0Usc0RBQWEsT0FBTSxVQUFuQixFQUE4QixVQUFTLFVBQXZDLEVBQWtELFFBQVEsS0FBSyxLQUFMLENBQVcsTUFBckU7QUFERixhQURGO0FBSUU7QUFBQTtBQUFBLGdCQUFLLFNBQU0sT0FBWDtBQUNFLHNEQUFhLE9BQU0sV0FBbkIsRUFBK0IsVUFBUyxXQUF4QyxFQUFvRCxRQUFRLEtBQUssS0FBTCxDQUFXLE1BQXZFO0FBREY7QUFKRixXQUxGO0FBYUUsa0RBQWEsUUFBUSxLQUFLLEtBQUwsQ0FBVyxNQUFoQyxHQWJGO0FBY0U7QUFBQTtBQUFBLGNBQUssU0FBTSxLQUFYO0FBQ0U7QUFBQTtBQUFBLGdCQUFLLFNBQU0sT0FBWDtBQUNFLG9EQUFXLFFBQVEsS0FBSyxLQUFMLENBQVcsTUFBOUI7QUFERixhQURGO0FBSUU7QUFBQTtBQUFBLGdCQUFLLFNBQU0sT0FBWDtBQUNFLGdEQUFPLFFBQVEsS0FBSyxLQUFMLENBQVcsTUFBMUIsRUFBa0MsVUFBUyxXQUEzQyxFQUF1RCxPQUFNLFdBQTdELEVBQXlFLFNBQVMsQ0FBQyxHQUFELEVBQU0sVUFBTixFQUFrQixPQUFsQixFQUEyQixHQUEzQixDQUFsRjtBQURGO0FBSkYsV0FkRjtBQXNCRTtBQUFBO0FBQUEsY0FBSyxTQUFNLEtBQVg7QUFDRTtBQUFBO0FBQUEsZ0JBQUssU0FBTSxPQUFYO0FBQ0UsZ0RBQU8sUUFBUSxLQUFLLEtBQUwsQ0FBVyxNQUExQixFQUFrQyxVQUFTLG9CQUEzQyxFQUFnRSxPQUFNLG9CQUF0RSxFQUEyRixTQUFTLENBQUMsR0FBRCxFQUFNLFlBQU4sRUFBb0IsT0FBcEIsRUFBNkIsR0FBN0IsQ0FBcEc7QUFERixhQURGO0FBSUU7QUFBQTtBQUFBLGdCQUFLLFNBQU0sT0FBWDtBQUNFLGdEQUFPLFFBQVEsS0FBSyxLQUFMLENBQVcsTUFBMUIsRUFBa0MsVUFBUyxXQUEzQyxFQUF1RCxPQUFNLFdBQTdELEVBQXlFLFNBQVMsQ0FBQyxHQUFELEVBQU0sS0FBTixFQUFhLE9BQWIsRUFBc0IsR0FBdEIsQ0FBbEYsRUFBOEcsV0FBVyxtQkFBQyxDQUFEO0FBQUEseUJBQVM7QUFBQTtBQUFBO0FBQUk7QUFBQTtBQUFBLHdCQUFHLE1BQU0sT0FBTyxFQUFFLEtBQWxCO0FBQTBCLHdCQUFFLEtBQUYsQ0FBUSxTQUFSLENBQWtCLENBQWxCLEVBQXFCLEVBQXJCLEVBQXlCLE9BQXpCLENBQWlDLFVBQWpDLEVBQTZDLEVBQTdDLEVBQWlELE9BQWpELENBQXlELFNBQXpELEVBQW9FLEVBQXBFO0FBQTFCO0FBQUosbUJBQVQ7QUFBQSxpQkFBekg7QUFERixhQUpGO0FBT0U7QUFBQTtBQUFBLGdCQUFLLFNBQU0sT0FBWDtBQUNFLGdEQUFPLFFBQVEsS0FBSyxLQUFMLENBQVcsTUFBMUIsRUFBa0MsVUFBUyxVQUEzQyxFQUFzRCxPQUFNLFVBQTVELEVBQXVFLFNBQVMsQ0FBQyxHQUFELEVBQU0sU0FBTixFQUFpQixPQUFqQixFQUEwQixHQUExQixDQUFoRixFQUFnSCxhQUFhLEtBQUssS0FBTCxDQUFXLFFBQXhJO0FBREY7QUFQRjtBQXRCRjtBQUZGLE9BREE7QUFzQ0E7Ozs7OztrQkFHVyxTOzs7QUNwRmY7Ozs7Ozs7O0FBRUE7O0FBQ0E7Ozs7QUFDQTs7Ozs7Ozs7Ozs7O0lBRU0sSzs7Ozs7Ozs7Ozs7NkJBQ0s7QUFDUCxhQUNFO0FBQUE7QUFBQTtBQUNFLDhDQUFXLFlBQVksS0FBdkIsR0FERjtBQUVFO0FBQUE7QUFBQSxZQUFLLFNBQU0sV0FBWDtBQUNFLGdEQUFXLFdBQVcsS0FBSyxLQUFMLENBQVcsT0FBakM7QUFERjtBQUZGLE9BREY7QUFRRDs7Ozs7O2tCQUdZLEs7OztBQ25CZjs7OztBQUVBOztBQUNBOzs7O0FBQ0E7Ozs7Ozs7Ozs7OztJQUVNLEc7OztBQUNKLGVBQVksS0FBWixFQUFtQjtBQUFBOztBQUFBLDBHQUNYLEtBRFc7O0FBR2pCLFVBQUssS0FBTCxHQUFhO0FBQ1gscUJBQWUsU0FBUyxNQUFULENBQWdCLE9BQWhCLENBQXdCLE1BQXhCLElBQWtDLENBQUM7QUFEdkMsS0FBYjtBQUhpQjtBQU1sQjs7Ozs2QkFFUTtBQUFBOztBQUNQO0FBQ0EsVUFBSSxLQUFLLEtBQUwsQ0FBVyxhQUFmLEVBQStCO0FBQzdCLGVBQU8sc0NBQVcsVUFBVTtBQUFBLG1CQUFNLE9BQUssUUFBTCxDQUFjLEVBQUUsZUFBZSxLQUFqQixFQUFkLENBQU47QUFBQSxXQUFyQixHQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxhQUFPLGtDQUFPLFNBQVM7QUFBQSxpQkFBTSxPQUFLLFFBQUwsQ0FBYyxFQUFFLGVBQWUsSUFBakIsRUFBZCxDQUFOO0FBQUEsU0FBaEIsR0FBUDtBQUNEOzs7Ozs7QUFHSCxvQkFBTyxlQUFDLEdBQUQsT0FBUCxFQUFnQixTQUFTLGNBQVQsQ0FBd0IsTUFBeEIsQ0FBaEI7OztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZKQTs7Ozs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDN3ZEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNoRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDM0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5a0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDak1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9GQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDblFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcitGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2d0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqaUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbmJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzc1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ24rQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDLzREQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDblVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbnhCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2K0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdGZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzlkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDeExBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ3JoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMxL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNyTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDOXFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RUE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDOURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3pFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDblVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN6TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2U0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzV0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzVtQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaCwgcmVuZGVyLCBDb21wb25lbnQgfSBmcm9tICdwcmVhY3QnO1xuaW1wb3J0ICogYXMgbnVtYmVycyBmcm9tICcuLi9saWIvbnVtYmVycy5qcyc7XG5pbXBvcnQgQ2xpZW50IGZyb20gJy4uL2xpYi9jbGllbnQuanMnO1xuY29uc3QgZGF5SW5TZWNvbmRzID0gNjAgKiA2MCAqIDI0O1xuXG5jbGFzcyBDb3VudFdpZGdldCBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpXG5cbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgY291bnQ6IDAsXG4gICAgICBwcmV2aW91c0NvdW50OiAwLFxuICAgICAgbG9hZGluZzogZmFsc2VcbiAgICB9XG5cbiAgICB0aGlzLmZldGNoRGF0YSA9IHRoaXMuZmV0Y2hEYXRhLmJpbmQodGhpcyk7XG4gICAgdGhpcy5mZXRjaERhdGEocHJvcHMucGVyaW9kKTtcbiAgfVxuXG4gIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHMobmV3UHJvcHMpIHtcbiAgICBpZih0aGlzLnByb3BzLnBlcmlvZCAhPSBuZXdQcm9wcy5wZXJpb2QpIHtcbiAgICAgIHRoaXMuZmV0Y2hEYXRhKG5ld1Byb3BzLnBlcmlvZClcbiAgICB9XG4gIH1cblxuICBmZXRjaERhdGEocGVyaW9kKSB7XG4gICAgY29uc3QgYmVmb3JlID0gTWF0aC5yb3VuZCgoK25ldyBEYXRlKCkgKSAvIDEwMDApO1xuICAgIGNvbnN0IGFmdGVyID0gYmVmb3JlIC0gKCBwZXJpb2QgKiBkYXlJblNlY29uZHMgKTtcbiAgICB0aGlzLnNldFN0YXRlKHsgbG9hZGluZzogdHJ1ZSB9KVxuXG4gICAgQ2xpZW50LnJlcXVlc3QoYCR7dGhpcy5wcm9wcy5lbmRwb2ludH0vY291bnQ/YmVmb3JlPSR7YmVmb3JlfSZhZnRlcj0ke2FmdGVyfWApXG4gICAgICAudGhlbigoZCkgPT4geyB0aGlzLnNldFN0YXRlKHsgbG9hZGluZzogZmFsc2UsIGNvdW50OiBkIH0pfSlcblxuICAgIC8vIHF1ZXJ5IHByZXZpb3VzIHBlcmlvZFxuICAgIGNvbnN0IHByZXZpb3VzQmVmb3JlID0gYWZ0ZXI7XG4gICAgY29uc3QgcHJldmlvdXNBZnRlciA9IHByZXZpb3VzQmVmb3JlIC0gKCBwZXJpb2QgKiBkYXlJblNlY29uZHMgKTtcbiAgICBDbGllbnQucmVxdWVzdChgJHt0aGlzLnByb3BzLmVuZHBvaW50fS9jb3VudD9iZWZvcmU9JHtwcmV2aW91c0JlZm9yZX0mYWZ0ZXI9JHtwcmV2aW91c0FmdGVyfWApXG4gICAgICAudGhlbigoZCkgPT4geyB0aGlzLnNldFN0YXRlKHsgcHJldmlvdXNDb3VudDogZCB9KX0pXG4gIH1cblxuICByZW5kZXJQZXJjZW50YWdlKCkge1xuICAgIC8vIHdhaXQgZm9yIHJlcXVlc3QgdG8gZmluaXNoXG4gICAgaWYoICEgdGhpcy5zdGF0ZS5wcmV2aW91c0NvdW50ICkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGNvbnN0IHBlcmNlbnRhZ2UgPSBNYXRoLnJvdW5kKCggdGhpcy5zdGF0ZS5jb3VudCAvIHRoaXMuc3RhdGUucHJldmlvdXNDb3VudCAqIDEwMCAtIDEwMCkpXG4gICAgcmV0dXJuIChcbiAgICAgIDxzbWFsbCBjbGFzcz17cGVyY2VudGFnZSA+IDAgPyAncG9zaXRpdmUnIDogJ25lZ2F0aXZlJ30+e3BlcmNlbnRhZ2V9JTwvc21hbGw+XG4gICAgKVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IGxvYWRpbmdPdmVybGF5ID0gdGhpcy5zdGF0ZS5sb2FkaW5nID8gPGRpdiBjbGFzcz1cImxvYWRpbmctb3ZlcmxheVwiPjxkaXY+PC9kaXY+PC9kaXY+IDogJyc7XG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXYgY2xhc3M9XCJibG9jayBjZW50ZXItdGV4dFwiPlxuICAgICAgICB7bG9hZGluZ092ZXJsYXl9XG4gICAgICAgIDxoNCBjbGFzcz1cIlwiPnt0aGlzLnByb3BzLnRpdGxlfTwvaDQ+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJiaWcgdGlueS1tYXJnaW5cIj57bnVtYmVycy5mb3JtYXRXaXRoQ29tbWEodGhpcy5zdGF0ZS5jb3VudCl9IHt0aGlzLnJlbmRlclBlcmNlbnRhZ2UoKX08L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIClcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBDb3VudFdpZGdldFxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBoLCByZW5kZXIsIENvbXBvbmVudCB9IGZyb20gJ3ByZWFjdCc7XG5cbmNvbnN0IGF2YWlsYWJsZVBlcmlvZHMgPSBbXG4gIHtcbiAgICBpZDogNyxcbiAgICBsYWJlbDogJ0xhc3QgNyBkYXlzJ1xuICB9LFxuICB7XG4gICAgaWQ6IDMwLFxuICAgIGxhYmVsOiAnTGFzdCAzMCBkYXlzJ1xuICB9LFxuICB7XG4gICAgaWQ6IDkwLFxuICAgIGxhYmVsOiAnTGFzdCBxdWFydGVyJ1xuICB9LFxuICB7XG4gICAgaWQ6IDM2MCxcbiAgICBsYWJlbDogJ0xhc3QgeWVhcidcbiAgfVxuXVxuXG5jbGFzcyBEYXRlUGlja2VyIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcylcblxuICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICBwZXJpb2Q6IHRoaXMucHJvcHMucGVyaW9kXG4gICAgfVxuXG4gICAgdGhpcy5zZXRQZXJpb2QgPSB0aGlzLnNldFBlcmlvZC5iaW5kKHRoaXMpXG4gIH1cblxuICBzZXRQZXJpb2QoZSkge1xuICAgIHZhciBuZXh0U3RhdGUgPSB7IHBlcmlvZDogcGFyc2VJbnQoZS50YXJnZXQudmFsdWUpIH1cbiAgICBpZih0aGlzLnN0YXRlLnBlcmlvZCAhPSBuZXh0U3RhdGUucGVyaW9kKSB7XG4gICAgICB0aGlzLnNldFN0YXRlKG5leHRTdGF0ZSlcbiAgICAgIHRoaXMucHJvcHMub25DaG9vc2UodGhpcy5zdGF0ZS5wZXJpb2QpO1xuICAgIH1cbiAgfVxuXG4gIHJlbmRlcigpIHtcbiAgICBjb25zdCBidXR0b25zID0gYXZhaWxhYmxlUGVyaW9kcy5tYXAoKHApID0+IHtcbiAgICAgIGxldCBjbGFzc05hbWUgPSAoIHAuaWQgPT0gdGhpcy5zdGF0ZS5wZXJpb2QgKSA/ICdhY3RpdmUnIDogJyc7XG4gICAgICByZXR1cm4gPGJ1dHRvbiB2YWx1ZT17cC5pZH0gY2xhc3M9e2NsYXNzTmFtZX0gb25DbGljaz17dGhpcy5zZXRQZXJpb2R9PntwLmxhYmVsfTwvYnV0dG9uPlxuICAgIH0pO1xuXG4gICAgcmV0dXJuIChcblxuICAgICAgPGRpdiBjbGFzcz1cInNtYWxsLW1hcmdpblwiPlxuICAgICAgICB7YnV0dG9uc31cbiAgICAgIDwvZGl2PlxuICAgIClcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBEYXRlUGlja2VyXG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGgsIHJlbmRlciwgQ29tcG9uZW50IH0gZnJvbSAncHJlYWN0JztcbmltcG9ydCBDbGllbnQgZnJvbSAnLi4vbGliL2NsaWVudC5qcyc7XG5pbXBvcnQgKiBhcyBudW1iZXJzIGZyb20gJy4uL2xpYi9udW1iZXJzLmpzJztcblxuaW1wb3J0ICogYXMgZDMgZnJvbSAnZDMnO1xuZDMudGlwID0gcmVxdWlyZSgnZDMtdGlwJyk7XG5cbmNvbnN0IGRheUluU2Vjb25kcyA9IDYwICogNjAgKiAyNDtcblxuZnVuY3Rpb24gQ2hhcnQoZWxlbWVudCwgc2hvd1ByaW1hcnksIHNob3dTZWNvbmRhcnkpIHtcbiAgdmFyIHBhZHQgPSAxMCwgcGFkYiA9IDIwLCBwYWRyID0gNDAsIHBhZGwgPSA0MCxcbiAgICAgIGggPSAzMDAsXG4gICAgICB3ID0gZWxlbWVudC5wYXJlbnROb2RlLmNsaWVudFdpZHRoIC0gcGFkbCAtIHBhZHIsXG4gICAgICB4ICA9IGQzLnNjYWxlQmFuZCgpLnJhbmdlKFswLCB3XSkucGFkZGluZygwLjIpLnJvdW5kKHRydWUpLFxuICAgICAgeSAgPSBkMy5zY2FsZUxpbmVhcigpLnJhbmdlKFtoLCAwXSksXG4gICAgICB5QXhpcyA9IGQzLmF4aXNMZWZ0KCkuc2NhbGUoeSkudGlja1NpemUoLXcgKyBwYWRsICsgcGFkciksXG4gICAgICB4QXhpcyA9IGQzLmF4aXNCb3R0b20oKS5zY2FsZSh4KSxcbiAgICAgIHByaW1hcnlEYXRhID0gW10sXG4gICAgICBzZWNvbmRhcnlEYXRhID0gW107XG5cbiAgdmFyIHBhZ2V2aWV3VGlwID0gZDMudGlwKClcbiAgICAgIC5hdHRyKCdjbGFzcycsICdkMy10aXAnKVxuICAgICAgLmh0bWwoKGQpID0+ICc8aDU+JysgZC5MYWJlbCArJzwvaDU+PHNwYW4+JyArIG51bWJlcnMuZm9ybWF0V2l0aENvbW1hKGQuVmFsdWUpICsgJzwvc3Bhbj4nICsgJyBwYWdldmlld3MnKVxuICAgICAgLm9mZnNldChbLTEyLCAwXSk7XG5cbiAgdmFyIHZpc2l0b3JUaXAgPSBkMy50aXAoKVxuICAgICAgLmF0dHIoJ2NsYXNzJywgJ2QzLXRpcCcpXG4gICAgICAuaHRtbCgoZCkgPT4gJzxoNT4nKyBkLkxhYmVsICsnPC9oNT48c3Bhbj4nICsgbnVtYmVycy5mb3JtYXRXaXRoQ29tbWEoZC5WYWx1ZSkgKyAnPC9zcGFuPicgKyAnIHZpc2l0b3JzJyApXG4gICAgICAub2Zmc2V0KFstMTIsIDBdKTtcblxuICB2YXIgZ3JhcGggPSBkMy5zZWxlY3QoJyNncmFwaCcpO1xuICB2YXIgdmlzID0gZ3JhcGhcbiAgICAgIC5hcHBlbmQoJ3N2ZycpXG4gICAgICAuYXR0cignd2lkdGgnLCB3ICsgcGFkbCArIHBhZHIpXG4gICAgICAuYXR0cignaGVpZ2h0JywgaCArIHBhZHQgKyBwYWRiKVxuICAgICAgLmFwcGVuZCgnZycpXG4gICAgICAuYXR0cigndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZSgnICsgcGFkbCArICcsJyArIHBhZHQgKyAnKScpO1xuXG4gIHZpcy5jYWxsKHBhZ2V2aWV3VGlwKTtcbiAgdmlzLmNhbGwodmlzaXRvclRpcCk7XG5cbiAgZnVuY3Rpb24gc2V0RGF0YShvbmUsIHR3bykge1xuICAgIHByaW1hcnlEYXRhID0gb25lO1xuICAgIHNlY29uZGFyeURhdGEgPSB0d287XG4gIH1cblxuICBmdW5jdGlvbiB0b2dnbGVCYXJzKG9uZSwgdHdvKSB7XG4gICAgc2hvd1ByaW1hcnkgPSBvbmU7XG4gICAgc2hvd1NlY29uZGFyeSA9IHR3bztcbiAgfVxuXG4gIGZ1bmN0aW9uIGRyYXcoKSB7XG4gICAgdmFyIG1heCA9IGQzLm1heChzaG93UHJpbWFyeSA/IHByaW1hcnlEYXRhIDogc2Vjb25kYXJ5RGF0YSwgKGQpID0+IGQuVmFsdWUpO1xuICAgIHZhciB0aWNrcyA9IHByaW1hcnlEYXRhLmxlbmd0aDtcbiAgICB2YXIgeFRpY2sgPSBNYXRoLnJvdW5kKHRpY2tzIC8gNyk7XG5cblxuICAgIHguZG9tYWluKHByaW1hcnlEYXRhLm1hcCgoZCkgPT4gZC5MYWJlbCkpXG4gICAgeS5kb21haW4oWzAsIChtYXggKiAxLjEpXSlcblxuICAgIC8vIGNsZWFyIGFsbCBwcmV2aW91cyBkYXRhXG4gICAgdmlzLnNlbGVjdEFsbCgnKicpLnJlbW92ZSgpO1xuXG4gICAgLy8gYXhlc1xuICAgIHZpcy5hcHBlbmQoXCJnXCIpXG4gICAgICAuYXR0cihcImNsYXNzXCIsIFwieSBheGlzXCIpXG4gICAgICAuY2FsbCh5QXhpcyk7XG5cbiAgICB2aXMuYXBwZW5kKFwiZ1wiKVxuICAgICAgLmF0dHIoXCJjbGFzc1wiLCBcInggYXhpc1wiKVxuICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoMCwnICsgaCArICcpJylcbiAgICAgIC5jYWxsKHhBeGlzKVxuICAgICAgLnNlbGVjdEFsbCgnZycpXG4gICAgICAuc3R5bGUoJ2Rpc3BsYXknLCAoZCwgaSkgPT4gaSAlIHhUaWNrICE9IDAgPyAnbm9uZScgOiAnYmxvY2snKVxuXG4gICAgLy8gYmFyc1xuICAgIGlmKCBzaG93UHJpbWFyeSApIHtcbiAgICAgIHZhciBiYXJzID0gdmlzLnNlbGVjdEFsbCgnZy5wcmltYXJ5LWJhcicpXG4gICAgICAgIC5kYXRhKHByaW1hcnlEYXRhKVxuICAgICAgICAuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3ByaW1hcnktYmFyJylcbiAgICAgICAgLmF0dHIoJ3RyYW5zZm9ybScsIGZ1bmN0aW9uIChkLCBpKSB7IHJldHVybiBcInRyYW5zbGF0ZShcIiArIHgoZC5MYWJlbCkgKyBcIiwgMClcIiB9KTtcblxuICAgICAgYmFycy5hcHBlbmQoJ3JlY3QnKVxuICAgICAgICAuYXR0cignd2lkdGgnLCB4LmJhbmR3aWR0aCgpKVxuICAgICAgICAuYXR0cignaGVpZ2h0JywgKGQpID0+IChoIC0geShkLlZhbHVlKSkgKVxuICAgICAgICAuYXR0cigneScsIChkKSA9PiB5KGQuVmFsdWUpKVxuICAgICAgICAub24oJ21vdXNlb3ZlcicsIHBhZ2V2aWV3VGlwLnNob3cpXG4gICAgICAgIC5vbignbW91c2VvdXQnLCBwYWdldmlld1RpcC5oaWRlKTtcbiAgICB9XG5cbiAgICBpZihzaG93U2Vjb25kYXJ5KSB7XG4gICAgICB2YXIgdmlzaXRvckJhcnMgPSB2aXMuc2VsZWN0QWxsKCdnLnN1Yi1iYXInKVxuICAgICAgICAuZGF0YShzZWNvbmRhcnlEYXRhKVxuICAgICAgICAuZW50ZXIoKVxuICAgICAgICAuYXBwZW5kKCdnJylcbiAgICAgICAgLmF0dHIoJ2NsYXNzJywgJ3N1Yi1iYXInKVxuICAgICAgICAuYXR0cigndHJhbnNmb3JtJywgKGQsIGkpID0+IFwidHJhbnNsYXRlKFwiICsgKCB4KGQuTGFiZWwpICsgKCB4LmJhbmR3aWR0aCgpICogMC4xNjY2NyApICkgKyBcIiwgMClcIik7XG5cbiAgICAgIHZpc2l0b3JCYXJzLmFwcGVuZCgncmVjdCcpXG4gICAgICAgIC5hdHRyKCd3aWR0aCcsIHguYmFuZHdpZHRoKCkgKiAwLjY2IClcbiAgICAgICAgLmF0dHIoJ2hlaWdodCcsIChkKSA9PiAoaCAtIHkoZC5WYWx1ZSkpIClcbiAgICAgICAgLmF0dHIoJ3knLCAoZCkgPT4geShkLlZhbHVlKSlcbiAgICAgICAgLm9uKCdtb3VzZW92ZXInLCB2aXNpdG9yVGlwLnNob3cpXG4gICAgICAgIC5vbignbW91c2VvdXQnLCB2aXNpdG9yVGlwLmhpZGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgJ2RyYXcnOiBkcmF3LFxuICAgICdzZXREYXRhJzogc2V0RGF0YSxcbiAgICAndG9nZ2xlQmFycyc6IHRvZ2dsZUJhcnMsXG4gIH1cbn1cblxuXG5jbGFzcyBHcmFwaCBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpXG5cbiAgICB0aGlzLmZldGNoRGF0YSA9IHRoaXMuZmV0Y2hEYXRhLmJpbmQodGhpcyk7XG4gICAgdGhpcy5yZWZyZXNoQ2hhcnQgPSB0aGlzLnJlZnJlc2hDaGFydC5iaW5kKHRoaXMpO1xuICAgIHRoaXMuZGF0YSA9IHtcbiAgICAgIHZpc2l0b3JzOiBudWxsLFxuICAgICAgcGFnZXZpZXdzOiBudWxsLFxuICAgIH1cbiAgfVxuXG4gIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgIHRoaXMuY2hhcnQgPSBuZXcgQ2hhcnQoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2dyYXBoJyksIHRoaXMucHJvcHMuc2hvd1BhZ2V2aWV3cywgdGhpcy5wcm9wcy5zaG93VmlzaXRvcnMpXG4gICAgdGhpcy5mZXRjaERhdGEodGhpcy5wcm9wcy5wZXJpb2QpXG4gIH1cblxuICBjb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzKG5ld1Byb3BzKSB7XG4gICAgaWYodGhpcy5wcm9wcy5wZXJpb2QgIT0gbmV3UHJvcHMucGVyaW9kKSB7XG4gICAgICB0aGlzLmZldGNoRGF0YShuZXdQcm9wcy5wZXJpb2QpXG4gICAgfVxuXG4gICAgdGhpcy5jaGFydC50b2dnbGVCYXJzKG5ld1Byb3BzLnNob3dQYWdldmlld3MsIG5ld1Byb3BzLnNob3dWaXNpdG9ycylcbiAgICB0aGlzLmNoYXJ0LmRyYXcoKVxuICB9XG5cbiAgc2hvdWxkQ29tcG9uZW50VXBkYXRlKCkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG5cbiAgcmVmcmVzaENoYXJ0KCkge1xuXG4gICAgaWYodGhpcy5kYXRhLnZpc2l0b3JzICYmIHRoaXMuZGF0YS5wYWdldmlld3MpIHtcbiAgICAgIHRoaXMubG9hZGluZ0luZGljYXRvci5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgdGhpcy5jaGFydC5zZXREYXRhKHRoaXMuZGF0YS5wYWdldmlld3MsIHRoaXMuZGF0YS52aXNpdG9ycylcbiAgICAgIHRoaXMuY2hhcnQuZHJhdygpXG4gICAgfVxuICB9XG5cbiAgZmV0Y2hEYXRhKHBlcmlvZCkge1xuICAgIGNvbnN0IGJlZm9yZSA9IE1hdGgucm91bmQoKCtuZXcgRGF0ZSgpICkgLyAxMDAwKTtcbiAgICBjb25zdCBhZnRlciA9IGJlZm9yZSAtICggcGVyaW9kICogZGF5SW5TZWNvbmRzICk7XG4gICAgY29uc3QgZ3JvdXAgPSBwZXJpb2QgPiA5MCA/ICdtb250aCcgOiAnZGF5JztcbiAgICB0aGlzLmxvYWRpbmdJbmRpY2F0b3Iuc3R5bGUuZGlzcGxheSA9ICcnO1xuXG4gICAgQ2xpZW50XG4gICAgICAucmVxdWVzdChgcGFnZXZpZXdzL2NvdW50L2dyb3VwLyR7Z3JvdXB9P2JlZm9yZT0ke2JlZm9yZX0mYWZ0ZXI9JHthZnRlcn1gKVxuICAgICAgLnRoZW4oKGQpID0+IHtcbiAgICAgICAgdGhpcy5kYXRhLnBhZ2V2aWV3cyA9IGQ7XG4gICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUodGhpcy5yZWZyZXNoQ2hhcnQpO1xuICAgICAgfSlcblxuICAgIENsaWVudFxuICAgICAgLnJlcXVlc3QoYHZpc2l0b3JzL2NvdW50L2dyb3VwLyR7Z3JvdXB9P2JlZm9yZT0ke2JlZm9yZX0mYWZ0ZXI9JHthZnRlcn1gKVxuICAgICAgLnRoZW4oKGQpID0+IHtcbiAgICAgICAgdGhpcy5kYXRhLnZpc2l0b3JzID0gZDtcbiAgICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSh0aGlzLnJlZnJlc2hDaGFydCk7XG4gICAgICB9KVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiAoXG4gICAgICA8ZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy1vdmVybGF5XCIgcmVmPXsoZWwpID0+IHsgdGhpcy5sb2FkaW5nSW5kaWNhdG9yID0gZWwgfX0+PGRpdj48L2Rpdj48L2Rpdj5cbiAgICAgICAgPGRpdiBpZD1cImdyYXBoXCI+PC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICApXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgR3JhcGhcbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaCwgcmVuZGVyLCBDb21wb25lbnQgfSBmcm9tICdwcmVhY3QnO1xuaW1wb3J0IEdyYXBoIGZyb20gJy4vR3JhcGguanMnO1xuXG5jbGFzcyBHcmFwaFdpZGdldCBleHRlbmRzIENvbXBvbmVudCB7XG5cbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcylcbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgc2hvd1BhZ2V2aWV3czogdHJ1ZSxcbiAgICAgIHNob3dWaXNpdG9yczogdHJ1ZSxcbiAgICB9XG4gIH1cblxuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXYgY2xhc3M9XCJibG9ja1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicHVsbC1yaWdodFwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImlubGluZSBzbWFsbC1tYXJnaW4tcmlnaHRcIj48aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgY2hlY2tlZD17dGhpcy5zdGF0ZS5zaG93UGFnZXZpZXdzfSBvbmNoYW5nZT17KGUpID0+IHRoaXMuc2V0U3RhdGUoeyBzaG93UGFnZXZpZXdzOiBlLnRhcmdldC5jaGVja2VkIH0pfSAvPiBQYWdldmlld3M8L2xhYmVsPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImlubGluZVwiPjxpbnB1dCB0eXBlPVwiY2hlY2tib3hcIiBjaGVja2VkPXt0aGlzLnN0YXRlLnNob3dWaXNpdG9yc30gb25jaGFuZ2U9eyhlKSA9PiB0aGlzLnNldFN0YXRlKHsgc2hvd1Zpc2l0b3JzOiBlLnRhcmdldC5jaGVja2VkIH0pfSAvPiBWaXNpdG9yczwvbGFiZWw+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8R3JhcGggcGVyaW9kPXt0aGlzLnByb3BzLnBlcmlvZH0gc2hvd1BhZ2V2aWV3cz17dGhpcy5zdGF0ZS5zaG93UGFnZXZpZXdzfSBzaG93VmlzaXRvcnM9e3RoaXMuc3RhdGUuc2hvd1Zpc2l0b3JzfSAvPlxuICAgICAgPC9kaXY+XG4gICAgKVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEdyYXBoV2lkZ2V0XG4iLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IHsgaCwgcmVuZGVyLCBDb21wb25lbnQgfSBmcm9tICdwcmVhY3QnO1xuaW1wb3J0IExvZ291dEJ1dHRvbiBmcm9tICcuLi9jb21wb25lbnRzL0xvZ291dEJ1dHRvbi5qcyc7XG5cbmNsYXNzIEhlYWRlckJhciBleHRlbmRzIENvbXBvbmVudCB7XG4gIHJlbmRlcigpIHtcbiAgICBjb25zdCByaWdodENvbnRlbnQgPSB0aGlzLnByb3BzLnNob3dMb2dvdXQgPyA8TG9nb3V0QnV0dG9uIG9uU3VjY2Vzcz17dGhpcy5wcm9wcy5vbkxvZ291dH0gLz4gOiAnJztcblxuICAgIHJldHVybiAoXG4gICAgICA8aGVhZGVyIGNsYXNzPVwiaGVhZGVyLWJhciBjZlwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29udGFpbmVyXCI+XG4gICAgICAgICAgPGgxIGNsYXNzPVwicHVsbC1sZWZ0IHRpdGxlXCI+QW5hIDxzbWFsbCBjbGFzcz1cInN1YnRpdGxlXCI+b3BlbiB3ZWIgYW5hbHl0aWNzPC9zbWFsbD48L2gxPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwdWxsLXJpZ2h0XCI+XG4gICAgICAgICAgICAgIHtyaWdodENvbnRlbnR9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9oZWFkZXI+XG4gICl9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEhlYWRlckJhclxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBoLCByZW5kZXIsIENvbXBvbmVudCB9IGZyb20gJ3ByZWFjdCc7XG5pbXBvcnQgQ2xpZW50IGZyb20gJy4uL2xpYi9jbGllbnQuanMnO1xuaW1wb3J0IE5vdGlmaWNhdGlvbiBmcm9tICcuLi9jb21wb25lbnRzL05vdGlmaWNhdGlvbi5qcyc7XG5cbmNsYXNzIExvZ2luRm9ybSBleHRlbmRzIENvbXBvbmVudCB7XG5cbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcylcbiAgICB0aGlzLmhhbmRsZVN1Ym1pdCA9IHRoaXMuaGFuZGxlU3VibWl0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgIGVtYWlsOiAnJyxcbiAgICAgIHBhc3N3b3JkOiAnJyxcbiAgICAgIG1lc3NhZ2U6ICcnXG4gICAgfVxuICB9XG5cbiAgaGFuZGxlU3VibWl0KGUpIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBDbGllbnQucmVxdWVzdCgnc2Vzc2lvbicsIHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICBkYXRhOiB7XG4gICAgICAgIGVtYWlsOiB0aGlzLnN0YXRlLmVtYWlsLFxuICAgICAgICBwYXNzd29yZDogdGhpcy5zdGF0ZS5wYXNzd29yZCxcbiAgICAgIH1cbiAgICB9KS50aGVuKChyKSA9PiB7XG4gICAgICAgIHRoaXMucHJvcHMub25TdWNjZXNzKClcbiAgICB9KS5jYXRjaCgoZSkgPT4ge1xuICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgIG1lc3NhZ2U6IGUubWVzc2FnZSxcbiAgICAgICAgcGFzc3dvcmQ6ICcnXG4gICAgICB9KVxuXG4gICAgfSlcbiAgfVxuXG4gIHJlbmRlcigpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPGRpdiBjbGFzcz1cImJsb2NrXCI+XG4gICAgICAgIDxoMj5Mb2dpbjwvaDI+XG4gICAgICAgIDxwPlBsZWFzZSBlbnRlciB5b3VyIGNyZWRlbnRpYWxzIHRvIGFjY2VzcyB5b3VyIEFuYSBkYXNoYm9hcmQuPC9wPlxuICAgICAgICA8Zm9ybSBtZXRob2Q9XCJQT1NUXCIgb25TdWJtaXQ9e3RoaXMuaGFuZGxlU3VibWl0fT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic21hbGwtbWFyZ2luXCI+XG4gICAgICAgICAgICA8bGFiZWw+RW1haWwgYWRkcmVzczwvbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXQgdHlwZT1cImVtYWlsXCIgbmFtZT1cImVtYWlsXCIgcGxhY2Vob2xkZXI9XCJFbWFpbCBhZGRyZXNzXCIgdmFsdWU9e3RoaXMuc3RhdGUuZW1haWx9IG9uQ2hhbmdlPXt0aGlzLmxpbmtTdGF0ZSgnZW1haWwnKX0gcmVxdWlyZWQ9XCJyZXF1aXJlZFwiIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInNtYWxsLW1hcmdpblwiPlxuICAgICAgICAgICAgPGxhYmVsPlBhc3N3b3JkPC9sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBuYW1lPVwicGFzc3dvcmRcIiBwbGFjZWhvbGRlcj1cIioqKioqKioqKipcIiB2YWx1ZT17dGhpcy5zdGF0ZS5wYXNzd29yZH0gb25DaGFuZ2U9e3RoaXMubGlua1N0YXRlKCdwYXNzd29yZCcpfSByZXF1aXJlZD1cInJlcXVpcmVkXCIgLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwic21hbGwtbWFyZ2luXCI+XG4gICAgICAgICAgICA8aW5wdXQgdHlwZT1cInN1Ym1pdFwiIHZhbHVlPVwiU2lnbiBpblwiIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZm9ybT5cbiAgICAgICAgPE5vdGlmaWNhdGlvbiBtZXNzYWdlPXt0aGlzLnN0YXRlLm1lc3NhZ2V9IGtpbmQ9XCJcIiAvPlxuICAgICAgPC9kaXY+XG5cbiAgICApXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTG9naW5Gb3JtXG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGgsIHJlbmRlciwgQ29tcG9uZW50IH0gZnJvbSAncHJlYWN0JztcbmltcG9ydCBDbGllbnQgZnJvbSAnLi4vbGliL2NsaWVudC5qcyc7XG5cbmNsYXNzIExvZ291dEJ1dHRvbiBleHRlbmRzIENvbXBvbmVudCB7XG5cbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcylcbiAgICB0aGlzLmhhbmRsZVN1Ym1pdCA9IHRoaXMuaGFuZGxlU3VibWl0LmJpbmQodGhpcyk7XG4gIH1cblxuICBoYW5kbGVTdWJtaXQoZSkge1xuICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgIENsaWVudC5yZXF1ZXN0KCdzZXNzaW9uJywge1xuICAgICAgbWV0aG9kOiBcIkRFTEVURVwiLFxuICAgIH0pLnRoZW4oKHIpID0+IHsgdGhpcy5wcm9wcy5vblN1Y2Nlc3MoKSB9KVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiAoXG4gICAgICA8YSBocmVmPVwiI1wiIG9uQ2xpY2s9e3RoaXMuaGFuZGxlU3VibWl0fT5TaWduIG91dDwvYT5cbiAgICApXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTG9nb3V0QnV0dG9uXG4iLCIndXNlIHN0cmljdCdcblxuaW1wb3J0IHsgaCwgcmVuZGVyLCBDb21wb25lbnQgfSBmcm9tICdwcmVhY3QnO1xuXG5jbGFzcyBOb3RpZmljYXRpb24gZXh0ZW5kcyBDb21wb25lbnQge1xuICBjb25zdHJ1Y3Rvcihwcm9wcykge1xuICAgIHN1cGVyKHByb3BzKVxuXG4gICAgdGhpcy5zdGF0ZSA9IHtcbiAgICAgIG1lc3NhZ2U6IHByb3BzLm1lc3NhZ2UsXG4gICAgICBraW5kOiBwcm9wcy5raW5kIHx8ICdlcnJvcidcbiAgICB9XG4gICAgdGhpcy50aW1lb3V0ID0gMFxuICB9XG5cbiAgY2xlYXJNZXNzYWdlKCkge1xuICAgIHRoaXMuc2V0U3RhdGUoeyBtZXNzYWdlOiAnJyB9KVxuICB9XG5cbiAgY29tcG9uZW50V2lsbFJlY2VpdmVQcm9wcyhuZXdQcm9wcykge1xuICAgIGlmKG5ld1Byb3BzLm1lc3NhZ2UgIT0gdGhpcy5zdGF0ZS5tZXNzYWdlKSB7XG4gICAgICB0aGlzLnNldFN0YXRlKHsgbWVzc2FnZTogbmV3UHJvcHMubWVzc2FnZSwga2luZDogbmV3UHJvcHMua2luZCB8fCAnZXJyb3InIH0pXG4gICAgICB3aW5kb3cuY2xlYXJUaW1lb3V0KHRoaXMudGltZW91dClcbiAgICAgIHRoaXMudGltZW91dCA9IHdpbmRvdy5zZXRUaW1lb3V0KHRoaXMuY2xlYXJNZXNzYWdlLmJpbmQodGhpcyksIDUwMDApXG4gICAgfVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIGlmKHRoaXMuc3RhdGUubWVzc2FnZSA9PT0gJycpIHtcbiAgICAgIHJldHVybiAnJ1xuICAgIH1cblxuICAgIHJldHVybiAoXG4gICAgICA8ZGl2IGNsYXNzPXtgbm90aWZpY2F0aW9uYH0+XG4gICAgICAgIDxkaXYgY2xhc3M9e2Bub3RpZmljYXRpb24tJHt0aGlzLnN0YXRlLmtpbmR9YH0+XG4gICAgICAgICAge3RoaXMuc3RhdGUubWVzc2FnZX1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgKX1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTm90aWZpY2F0aW9uXG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGgsIHJlbmRlciwgQ29tcG9uZW50IH0gZnJvbSAncHJlYWN0JztcbmltcG9ydCAqIGFzIG51bWJlcnMgZnJvbSAnLi4vbGliL251bWJlcnMuanMnO1xuaW1wb3J0IENsaWVudCBmcm9tICcuLi9saWIvY2xpZW50LmpzJztcblxuY29uc3QgZGF5SW5TZWNvbmRzID0gNjAgKiA2MCAqIDI0O1xuXG5jbGFzcyBQYWdldmlld3MgZXh0ZW5kcyBDb21wb25lbnQge1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpXG5cbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgcmVjb3JkczogW10sXG4gICAgICBsb2FkaW5nOiBmYWxzZVxuICAgIH1cbiAgICB0aGlzLmZldGNoUmVjb3JkcyA9IHRoaXMuZmV0Y2hSZWNvcmRzLmJpbmQodGhpcyk7XG4gIH1cblxuICBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICB0aGlzLmZldGNoUmVjb3Jkcyh0aGlzLnByb3BzLnBlcmlvZClcbiAgfVxuXG4gIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHMobmV3UHJvcHMpIHtcbiAgICBpZih0aGlzLnByb3BzLnBlcmlvZCAhPSBuZXdQcm9wcy5wZXJpb2QpIHtcbiAgICAgIHRoaXMuZmV0Y2hSZWNvcmRzKG5ld1Byb3BzLnBlcmlvZClcbiAgICB9XG4gIH1cblxuICBmZXRjaFJlY29yZHMocGVyaW9kKSB7XG4gICAgY29uc3QgYmVmb3JlID0gTWF0aC5yb3VuZCgoK25ldyBEYXRlKCkgKSAvIDEwMDApO1xuICAgIGNvbnN0IGFmdGVyID0gYmVmb3JlIC0gKCBwZXJpb2QgKiBkYXlJblNlY29uZHMgKTtcbiAgICB0aGlzLnNldFN0YXRlKHsgbG9hZGluZzogdHJ1ZSB9KVxuXG4gICAgQ2xpZW50LnJlcXVlc3QoYHBhZ2V2aWV3cz9iZWZvcmU9JHtiZWZvcmV9JmFmdGVyPSR7YWZ0ZXJ9YClcbiAgICAudGhlbigoZCkgPT4geyB0aGlzLnNldFN0YXRlKHsgbG9hZGluZzogZmFsc2UsIHJlY29yZHM6IGQgfSl9KVxuICAgIC5jYXRjaCgoZSkgPT4geyBjb25zb2xlLmxvZyhlKSB9KVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IGxvYWRpbmdPdmVybGF5ID0gdGhpcy5zdGF0ZS5sb2FkaW5nID8gPGRpdiBjbGFzcz1cImxvYWRpbmctb3ZlcmxheVwiPjxkaXY+PC9kaXY+PC9kaXY+IDogJyc7XG4gICAgY29uc3QgdGFibGVSb3dzID0gdGhpcy5zdGF0ZS5yZWNvcmRzLm1hcCggKHAsIGkpID0+IChcbiAgICAgIDx0cj5cbiAgICAgICAgPHRkIGNsYXNzPVwibXV0ZWRcIj57aSsxfTwvdGQ+XG4gICAgICAgIDx0ZD48YSBocmVmPXtcIi8vXCIgKyBwLkhvc3RuYW1lICsgcC5QYXRofT57cC5QYXRoLnN1YnN0cmluZygwLCA1MCl9e3AuUGF0aC5sZW5ndGggPiA1MCA/ICcuLicgOiAnJ308L2E+PC90ZD5cbiAgICAgICAgPHRkPntudW1iZXJzLmZvcm1hdFdpdGhDb21tYShwLkNvdW50KX08L3RkPlxuICAgICAgICA8dGQ+e251bWJlcnMuZm9ybWF0V2l0aENvbW1hKHAuQ291bnRVbmlxdWUpfTwvdGQ+XG4gICAgICA8L3RyPlxuICAgICkpO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXYgY2xhc3M9XCJibG9ja1wiPlxuICAgICAgICB7bG9hZGluZ092ZXJsYXl9XG4gICAgICAgIDxoMz5QYWdldmlld3M8L2gzPlxuICAgICAgICA8dGFibGUgY2xhc3M9XCJ0YWJsZSBwYWdldmlld3NcIj5cbiAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgIDx0aD4jPC90aD5cbiAgICAgICAgICAgICAgPHRoPlVSTDwvdGg+XG4gICAgICAgICAgICAgIDx0aD5QYWdldmlld3M8L3RoPlxuICAgICAgICAgICAgICA8dGg+VW5pcXVlPC90aD5cbiAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICA8dGJvZHk+e3RhYmxlUm93c308L3Rib2R5PlxuICAgICAgICA8L3RhYmxlPlxuICAgICAgPC9kaXY+XG4gICAgKVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFBhZ2V2aWV3c1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBoLCByZW5kZXIsIENvbXBvbmVudCB9IGZyb20gJ3ByZWFjdCc7XG5pbXBvcnQgQ2xpZW50IGZyb20gJy4uL2xpYi9jbGllbnQuanMnO1xuXG5jbGFzcyBSZWFsdGltZSBleHRlbmRzIENvbXBvbmVudCB7XG5cbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcylcblxuICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICBjb3VudDogMFxuICAgIH1cbiAgICB0aGlzLmZldGNoRGF0YSA9IHRoaXMuZmV0Y2hEYXRhLmJpbmQodGhpcyk7XG4gICAgdGhpcy5mZXRjaERhdGEoKTtcbiAgICB3aW5kb3cuc2V0SW50ZXJ2YWwodGhpcy5mZXRjaERhdGEsIDE1MDAwKTtcbiAgfVxuXG4gIGZldGNoRGF0YSgpIHtcbiAgICBDbGllbnQucmVxdWVzdChgdmlzaXRvcnMvY291bnQvcmVhbHRpbWVgKVxuICAgICAgLnRoZW4oKGQpID0+IHsgdGhpcy5zZXRTdGF0ZSh7IGNvdW50OiBkIH0pfSlcbiAgfVxuXG4gIHJlbmRlcigpIHtcbiAgICBsZXQgdmlzaXRvcnMgPSB0aGlzLnN0YXRlLmNvdW50ID09IDEgPyAndmlzaXRvcicgOiAndmlzaXRvcnMnO1xuICAgIHJldHVybiAoXG4gICAgICA8ZGl2IGNsYXNzPVwiYmxvY2sgYmxvY2stZmxvYXRcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJjb3VudFwiPnt0aGlzLnN0YXRlLmNvdW50fTwvc3Bhbj4gPHNwYW4+e3Zpc2l0b3JzfSBvbiB0aGUgc2l0ZSByaWdodCBub3cuPC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgKVxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFJlYWx0aW1lXG4iLCIndXNlIHN0cmljdCc7XG5cbmltcG9ydCB7IGgsIHJlbmRlciwgQ29tcG9uZW50IH0gZnJvbSAncHJlYWN0JztcbmltcG9ydCAqIGFzIG51bWJlcnMgZnJvbSAnLi4vbGliL251bWJlcnMuanMnO1xuaW1wb3J0IENsaWVudCBmcm9tICcuLi9saWIvY2xpZW50LmpzJztcbmNvbnN0IGRheUluU2Vjb25kcyA9IDYwICogNjAgKiAyNDtcblxuY2xhc3MgVGFibGUgZXh0ZW5kcyBDb21wb25lbnQge1xuXG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpXG5cbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgcmVjb3JkczogW10sXG4gICAgICBsaW1pdDogNSxcbiAgICAgIGxvYWRpbmc6IHRydWVcbiAgICB9XG5cbiAgICB0aGlzLnRhYmxlSGVhZGVycyA9IHByb3BzLmhlYWRlcnMubWFwKGhlYWRpbmcgPT4gPHRoPntoZWFkaW5nfTwvdGg+KVxuICAgIHRoaXMuZmV0Y2hSZWNvcmRzID0gdGhpcy5mZXRjaFJlY29yZHMuYmluZCh0aGlzKVxuICAgIHRoaXMuaGFuZGxlTGltaXRDaG9pY2UgPSB0aGlzLmhhbmRsZUxpbWl0Q2hvaWNlLmJpbmQodGhpcylcbiAgfVxuXG4gIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgdGhpcy5mZXRjaFJlY29yZHModGhpcy5wcm9wcy5wZXJpb2QsIHRoaXMuc3RhdGUubGltaXQpXG4gIH1cblxuICBsYWJlbENlbGwocCkge1xuICAgIGlmKCB0aGlzLnByb3BzLmxhYmVsQ2VsbCApIHtcbiAgICAgIHJldHVybiB0aGlzLnByb3BzLmxhYmVsQ2VsbChwKVxuICAgIH1cblxuICAgIHJldHVybiAoXG4gICAgICA8dGQ+e3AuTGFiZWwuc3Vic3RyaW5nKDAsIDE1KX08L3RkPlxuICAgIClcbiAgfVxuXG4gIGNvbXBvbmVudFdpbGxSZWNlaXZlUHJvcHMobmV3UHJvcHMpIHtcbiAgICBpZih0aGlzLnByb3BzLnBlcmlvZCAhPSBuZXdQcm9wcy5wZXJpb2QpIHtcbiAgICAgIHRoaXMuZmV0Y2hSZWNvcmRzKG5ld1Byb3BzLnBlcmlvZCwgdGhpcy5zdGF0ZS5saW1pdClcbiAgICB9XG4gIH1cblxuICBoYW5kbGVMaW1pdENob2ljZShlKSB7XG4gICAgdGhpcy5zZXRTdGF0ZSh7IGxpbWl0OiBwYXJzZUludChlLnRhcmdldC52YWx1ZSkgfSlcbiAgICB0aGlzLmZldGNoUmVjb3Jkcyh0aGlzLnByb3BzLnBlcmlvZCwgdGhpcy5zdGF0ZS5saW1pdClcbiAgfVxuXG4gIGZldGNoUmVjb3JkcyhwZXJpb2QsIGxpbWl0KSB7XG4gICAgdGhpcy5zZXRTdGF0ZSh7IGxvYWRpbmc6IHRydWUgfSk7XG4gICAgY29uc3QgYmVmb3JlID0gTWF0aC5yb3VuZCgoK25ldyBEYXRlKCkgKSAvIDEwMDApO1xuICAgIGNvbnN0IGFmdGVyID0gYmVmb3JlIC0gKCBwZXJpb2QgKiBkYXlJblNlY29uZHMgKTtcblxuICAgIENsaWVudC5yZXF1ZXN0KGAke3RoaXMucHJvcHMuZW5kcG9pbnR9P2JlZm9yZT0ke2JlZm9yZX0mYWZ0ZXI9JHthZnRlcn0mbGltaXQ9JHtsaW1pdH1gKVxuICAgICAgLnRoZW4oKGQpID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IGxvYWRpbmc6IGZhbHNlLCByZWNvcmRzOiBkIH1cbiAgICAgICl9KS5jYXRjaCgoZSkgPT4geyBjb25zb2xlLmxvZyhlKSB9KVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIGNvbnN0IHRhYmxlUm93cyA9IHRoaXMuc3RhdGUucmVjb3Jkcy5sZW5ndGggPiAwID8gdGhpcy5zdGF0ZS5yZWNvcmRzLm1hcCgocCwgaSkgPT4gKFxuICAgICAgPHRyPlxuICAgICAgICA8dGQgY2xhc3M9XCJtdXRlZFwiPntpKzF9PC90ZD5cbiAgICAgICAge3RoaXMubGFiZWxDZWxsKHApfVxuICAgICAgICA8dGQ+e251bWJlcnMuZm9ybWF0V2l0aENvbW1hKHAuVmFsdWUpfTwvdGQ+XG4gICAgICAgIDx0ZD57TWF0aC5yb3VuZChwLlBlcmNlbnRhZ2VWYWx1ZSl9JTwvdGQ+XG4gICAgICA8L3RyPlxuICAgICkpIDo8dHI+PHRkIGNvbHNwYW49XCI0XCIgY2xhc3M9XCJpdGFsaWNcIj5Ob3RoaW5nIGhlcmUuLjwvdGQ+PC90cj47XG5cbiAgICBjb25zdCBsb2FkaW5nT3ZlcmxheSA9IHRoaXMuc3RhdGUubG9hZGluZyA/IDxkaXYgY2xhc3M9XCJsb2FkaW5nLW92ZXJsYXlcIj48ZGl2PjwvZGl2PjwvZGl2PiA6ICcnO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIDxkaXYgY2xhc3M9XCJibG9ja1wiPlxuICAgICAgICB7bG9hZGluZ092ZXJsYXl9XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjbGVhcmZpeFwiPlxuICAgICAgICAgIDxoMyBjbGFzcz1cInB1bGwtbGVmdFwiPnt0aGlzLnByb3BzLnRpdGxlfTwvaDM+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInB1bGwtcmlnaHRcIj5cbiAgICAgICAgICAgIDxzZWxlY3Qgb25jaGFuZ2U9e3RoaXMuaGFuZGxlTGltaXRDaG9pY2V9PlxuICAgICAgICAgICAgICA8b3B0aW9uPjU8L29wdGlvbj5cbiAgICAgICAgICAgICAgPG9wdGlvbj4yMDwvb3B0aW9uPlxuICAgICAgICAgICAgICA8b3B0aW9uPjEwMDwvb3B0aW9uPlxuICAgICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDx0YWJsZT5cbiAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICA8dHI+e3RoaXMudGFibGVIZWFkZXJzfTwvdHI+XG4gICAgICAgICAgPC90aGVhZD5cbiAgICAgICAgICA8dGJvZHk+XG4gICAgICAgICAgICB7dGFibGVSb3dzfVxuICAgICAgICAgIDwvdGJvZHk+XG4gICAgICAgIDwvdGFibGU+XG4gICAgICA8L2Rpdj5cbiAgICApXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgVGFibGVcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIENsaWVudCA9IHt9O1xuQ2xpZW50LnJlcXVlc3QgPSBmdW5jdGlvbihyZXNvdXJjZSwgYXJncykge1xuICBhcmdzID0gYXJncyB8fCB7fTtcbiAgYXJncy5jcmVkZW50aWFscyA9ICdzYW1lLW9yaWdpbidcbiAgYXJncy5oZWFkZXJzID0gYXJncy5oZWFkZXJzIHx8IHt9O1xuICBhcmdzLmhlYWRlcnNbJ0FjY2VwdCddID0gJ2FwcGxpY2F0aW9uL2pzb24nO1xuXG4gIGlmKCBhcmdzLm1ldGhvZCAmJiBhcmdzLm1ldGhvZCA9PT0gJ1BPU1QnKSB7XG4gICAgYXJncy5oZWFkZXJzWydDb250ZW50LVR5cGUnXSA9ICdhcHBsaWNhdGlvbi9qc29uJztcblxuICAgIGlmKGFyZ3MuZGF0YSkge1xuICAgICAgaWYoIHR5cGVvZihhcmdzLmRhdGEpICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIGFyZ3MuZGF0YSA9IEpTT04uc3RyaW5naWZ5KGFyZ3MuZGF0YSlcbiAgICAgIH1cbiAgICAgIGFyZ3MuYm9keSA9IGFyZ3MuZGF0YVxuICAgICAgZGVsZXRlIGFyZ3MuZGF0YVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmZXRjaChgL2FwaS8ke3Jlc291cmNlfWAsIGFyZ3MpXG4gICAgLnRoZW4ocGFyc2VKU09OKVxuICAgIC50aGVuKGNoZWNrRGF0YSlcbn1cblxuZnVuY3Rpb24gcGFyc2VKU09OKHIpIHtcbiAgcmV0dXJuIHIuanNvbigpXG59XG5cbmZ1bmN0aW9uIGNoZWNrRGF0YShkKSB7XG4gIGlmKGQuRXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoZC5FcnJvcilcbiAgfVxuXG4gIHJldHVybiBkLkRhdGFcbn1cblxuZXhwb3J0IGRlZmF1bHQgQ2xpZW50XG4iLCJmdW5jdGlvbiBmb3JtYXRXaXRoQ29tbWEoblN0cikge1xuXHRuU3RyICs9ICcnO1xuXG4gIGlmKG5TdHIubGVuZ3RoIDwgNCApIHtcbiAgICByZXR1cm4gblN0cjtcbiAgfVxuXG4gIHZhclx0eCA9IG5TdHIuc3BsaXQoJy4nKTtcblx0dmFyIHgxID0geFswXTtcblx0dmFyIHgyID0geC5sZW5ndGggPiAxID8gJy4nICsgeFsxXSA6ICcnO1xuXHR2YXIgcmd4ID0gLyhcXGQrKShcXGR7M30pLztcblx0d2hpbGUgKHJneC50ZXN0KHgxKSkge1xuXHRcdHgxID0geDEucmVwbGFjZShyZ3gsICckMScgKyAnLCcgKyAnJDInKTtcblx0fVxuXHRyZXR1cm4geDEgKyB4Mjtcbn1cblxuZXhwb3J0IHsgZm9ybWF0V2l0aENvbW1hIH1cbiIsIid1c2Ugc3RyaWN0J1xuXG5pbXBvcnQgeyBoLCByZW5kZXIsIENvbXBvbmVudCB9IGZyb20gJ3ByZWFjdCc7XG5pbXBvcnQgUGFnZXZpZXdzIGZyb20gJy4uL2NvbXBvbmVudHMvUGFnZXZpZXdzLmpzJztcbmltcG9ydCBSZWFsdGltZSBmcm9tICcuLi9jb21wb25lbnRzL1JlYWx0aW1lLmpzJztcbmltcG9ydCBHcmFwaFdpZGdldCBmcm9tICcuLi9jb21wb25lbnRzL0dyYXBoV2lkZ2V0LmpzJztcbmltcG9ydCBEYXRlUGlja2VyIGZyb20gJy4uL2NvbXBvbmVudHMvRGF0ZVBpY2tlci5qcyc7XG5pbXBvcnQgVGFibGUgZnJvbSAnLi4vY29tcG9uZW50cy9UYWJsZS5qcyc7XG5pbXBvcnQgSGVhZGVyQmFyIGZyb20gJy4uL2NvbXBvbmVudHMvSGVhZGVyQmFyLmpzJztcbmltcG9ydCBDb3VudFdpZGdldCBmcm9tICcuLi9jb21wb25lbnRzL0NvdW50V2lkZ2V0LmpzJztcblxuZnVuY3Rpb24gcmVtb3ZlSW1nRWxlbWVudChlKSB7XG4gIGUudGFyZ2V0LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZS50YXJnZXQpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRDb3VudHJ5TGFiZWwocCkge1xuICBjb25zdCBzcmMgPSBcIi9zdGF0aWMvaW1nL2NvdW50cnktZmxhZ3MvXCIrIHAuTGFiZWwudG9Mb3dlckNhc2UoKSArXCIucG5nXCJcblxuICByZXR1cm4gKFxuICAgIDx0ZD5cbiAgICAgIHtwLkxhYmVsfVxuICAgICAgPGltZyBoZWlnaHQ9XCIxMlwiIHNyYz17c3JjfSBjbGFzcz1cInB1bGwtcmlnaHRcIiBvbkVycm9yPXtyZW1vdmVJbWdFbGVtZW50fSAvPlxuICAgIDwvdGQ+XG4gIClcbn1cblxuY2xhc3MgRGFzaGJvYXJkIGV4dGVuZHMgQ29tcG9uZW50IHtcbiAgY29uc3RydWN0b3IocHJvcHMpIHtcbiAgICBzdXBlcihwcm9wcylcblxuICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICBwZXJpb2Q6IHBhcnNlSW50KHdpbmRvdy5sb2NhdGlvbi5oYXNoLnN1YnN0cmluZygyKSkgfHwgN1xuICAgIH1cblxuICAgIHRoaXMub25QZXJpb2RDaG9vc2UgPSB0aGlzLm9uUGVyaW9kQ2hvb3NlLmJpbmQodGhpcylcbiAgfVxuXG4gIG9uUGVyaW9kQ2hvb3NlKHApIHtcbiAgICB0aGlzLnNldFN0YXRlKHsgcGVyaW9kOiBwIH0pXG4gICAgd2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKHRoaXMuc3RhdGUsIG51bGwsIGAjISR7cH1gKVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIHJldHVybiAoXG4gICAgPGRpdj5cbiAgICAgIDxIZWFkZXJCYXIgc2hvd0xvZ291dD17dHJ1ZX0gb25Mb2dvdXQ9e3RoaXMucHJvcHMub25Mb2dvdXR9IC8+XG4gICAgICA8ZGl2IGNsYXNzPVwiY29udGFpbmVyXCI+XG4gICAgICAgIDxSZWFsdGltZSAvPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2xlYXJcIj5cbiAgICAgICAgICA8RGF0ZVBpY2tlciBwZXJpb2Q9e3RoaXMuc3RhdGUucGVyaW9kfSBvbkNob29zZT17dGhpcy5vblBlcmlvZENob29zZX0gLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTJcIj5cbiAgICAgICAgICAgIDxDb3VudFdpZGdldCB0aXRsZT1cIlZpc2l0b3JzXCIgZW5kcG9pbnQ9XCJ2aXNpdG9yc1wiIHBlcmlvZD17dGhpcy5zdGF0ZS5wZXJpb2R9IC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0yXCI+XG4gICAgICAgICAgICA8Q291bnRXaWRnZXQgdGl0bGU9XCJQYWdldmlld3NcIiBlbmRwb2ludD1cInBhZ2V2aWV3c1wiIHBlcmlvZD17dGhpcy5zdGF0ZS5wZXJpb2R9IC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8R3JhcGhXaWRnZXQgcGVyaW9kPXt0aGlzLnN0YXRlLnBlcmlvZH0gLz5cbiAgICAgICAgPGRpdiBjbGFzcz1cInJvd1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtNFwiPlxuICAgICAgICAgICAgPFBhZ2V2aWV3cyBwZXJpb2Q9e3RoaXMuc3RhdGUucGVyaW9kfSAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMlwiPlxuICAgICAgICAgICAgPFRhYmxlIHBlcmlvZD17dGhpcy5zdGF0ZS5wZXJpb2R9IGVuZHBvaW50PVwibGFuZ3VhZ2VzXCIgdGl0bGU9XCJMYW5ndWFnZXNcIiBoZWFkZXJzPXtbXCIjXCIsIFwiTGFuZ3VhZ2VcIiwgXCJDb3VudFwiLCBcIiVcIl19IC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwicm93XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0yXCI+XG4gICAgICAgICAgICA8VGFibGUgcGVyaW9kPXt0aGlzLnN0YXRlLnBlcmlvZH0gZW5kcG9pbnQ9XCJzY3JlZW4tcmVzb2x1dGlvbnNcIiB0aXRsZT1cIlNjcmVlbiBSZXNvbHV0aW9uc1wiIGhlYWRlcnM9e1tcIiNcIiwgXCJSZXNvbHV0aW9uXCIsIFwiQ291bnRcIiwgXCIlXCJdfSAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMlwiPlxuICAgICAgICAgICAgPFRhYmxlIHBlcmlvZD17dGhpcy5zdGF0ZS5wZXJpb2R9IGVuZHBvaW50PVwicmVmZXJyZXJzXCIgdGl0bGU9XCJSZWZlcnJlcnNcIiBoZWFkZXJzPXtbXCIjXCIsIFwiVVJMXCIsIFwiQ291bnRcIiwgXCIlXCJdfSBsYWJlbENlbGw9eyhwKSA9PiAoIDx0ZD48YSBocmVmPXtcIi8vXCIgKyBwLkxhYmVsfT57cC5MYWJlbC5zdWJzdHJpbmcoMCwgMTUpLnJlcGxhY2UoJ2h0dHBzOi8vJywgJycpLnJlcGxhY2UoJ2h0dHA6Ly8nLCAnJyl9PC9hPjwvdGQ+KX0gLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTJcIj5cbiAgICAgICAgICAgIDxUYWJsZSBwZXJpb2Q9e3RoaXMuc3RhdGUucGVyaW9kfSBlbmRwb2ludD1cImJyb3dzZXJzXCIgdGl0bGU9XCJCcm93c2Vyc1wiIGhlYWRlcnM9e1tcIiNcIiwgXCJCcm93c2VyXCIsIFwiQ291bnRcIiwgXCIlXCJdfSBvbkF1dGhFcnJvcj17dGhpcy5wcm9wcy5vbkxvZ291dH0gLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gICl9XG59XG5cbmV4cG9ydCBkZWZhdWx0IERhc2hib2FyZFxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pbXBvcnQgeyBoLCByZW5kZXIsIENvbXBvbmVudCB9IGZyb20gJ3ByZWFjdCc7XG5pbXBvcnQgTG9naW5Gb3JtIGZyb20gJy4uL2NvbXBvbmVudHMvTG9naW5Gb3JtLmpzJztcbmltcG9ydCBIZWFkZXJCYXIgZnJvbSAnLi4vY29tcG9uZW50cy9IZWFkZXJCYXIuanMnO1xuXG5jbGFzcyBMb2dpbiBleHRlbmRzIENvbXBvbmVudCB7XG4gIHJlbmRlcigpIHtcbiAgICByZXR1cm4gKFxuICAgICAgPGRpdj5cbiAgICAgICAgPEhlYWRlckJhciBzaG93TG9nb3V0PXtmYWxzZX0gLz5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbnRhaW5lclwiPlxuICAgICAgICAgIDxMb2dpbkZvcm0gb25TdWNjZXNzPXt0aGlzLnByb3BzLm9uTG9naW59Lz5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICApXG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTG9naW5cbiIsIid1c2Ugc3RyaWN0JztcblxuaW1wb3J0IHsgaCwgcmVuZGVyLCBDb21wb25lbnQgfSBmcm9tICdwcmVhY3QnXG5pbXBvcnQgTG9naW4gZnJvbSAnLi9wYWdlcy9sb2dpbi5qcydcbmltcG9ydCBEYXNoYm9hcmQgZnJvbSAnLi9wYWdlcy9kYXNoYm9hcmQuanMnXG5cbmNsYXNzIEFwcCBleHRlbmRzIENvbXBvbmVudCB7XG4gIGNvbnN0cnVjdG9yKHByb3BzKSB7XG4gICAgc3VwZXIocHJvcHMpXG5cbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgYXV0aGVudGljYXRlZDogZG9jdW1lbnQuY29va2llLmluZGV4T2YoJ2F1dGgnKSA+IC0xXG4gICAgfVxuICB9XG5cbiAgcmVuZGVyKCkge1xuICAgIC8vIGxvZ2dlZC1pblxuICAgIGlmKCB0aGlzLnN0YXRlLmF1dGhlbnRpY2F0ZWQgKSB7XG4gICAgICByZXR1cm4gPERhc2hib2FyZCBvbkxvZ291dD17KCkgPT4gdGhpcy5zZXRTdGF0ZSh7IGF1dGhlbnRpY2F0ZWQ6IGZhbHNlIH0pfSAvPlxuICAgIH1cblxuICAgIC8vIGxvZ2dlZC1vdXRcbiAgICByZXR1cm4gPExvZ2luIG9uTG9naW49eygpID0+IHRoaXMuc2V0U3RhdGUoeyBhdXRoZW50aWNhdGVkOiB0cnVlIH0pfSAvPlxuICB9XG59XG5cbnJlbmRlcig8QXBwIC8+LCBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncm9vdCcpKTtcbiIsIid1c2Ugc3RyaWN0J1xuXG5leHBvcnRzLmJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoXG5leHBvcnRzLnRvQnl0ZUFycmF5ID0gdG9CeXRlQXJyYXlcbmV4cG9ydHMuZnJvbUJ5dGVBcnJheSA9IGZyb21CeXRlQXJyYXlcblxudmFyIGxvb2t1cCA9IFtdXG52YXIgcmV2TG9va3VwID0gW11cbnZhciBBcnIgPSB0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcgPyBVaW50OEFycmF5IDogQXJyYXlcblxudmFyIGNvZGUgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLydcbmZvciAodmFyIGkgPSAwLCBsZW4gPSBjb2RlLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gIGxvb2t1cFtpXSA9IGNvZGVbaV1cbiAgcmV2TG9va3VwW2NvZGUuY2hhckNvZGVBdChpKV0gPSBpXG59XG5cbi8vIFN1cHBvcnQgZGVjb2RpbmcgVVJMLXNhZmUgYmFzZTY0IHN0cmluZ3MsIGFzIE5vZGUuanMgZG9lcy5cbi8vIFNlZTogaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQmFzZTY0I1VSTF9hcHBsaWNhdGlvbnNcbnJldkxvb2t1cFsnLScuY2hhckNvZGVBdCgwKV0gPSA2MlxucmV2TG9va3VwWydfJy5jaGFyQ29kZUF0KDApXSA9IDYzXG5cbmZ1bmN0aW9uIGdldExlbnMgKGI2NCkge1xuICB2YXIgbGVuID0gYjY0Lmxlbmd0aFxuXG4gIGlmIChsZW4gJSA0ID4gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBzdHJpbmcuIExlbmd0aCBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNCcpXG4gIH1cblxuICAvLyBUcmltIG9mZiBleHRyYSBieXRlcyBhZnRlciBwbGFjZWhvbGRlciBieXRlcyBhcmUgZm91bmRcbiAgLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vYmVhdGdhbW1pdC9iYXNlNjQtanMvaXNzdWVzLzQyXG4gIHZhciB2YWxpZExlbiA9IGI2NC5pbmRleE9mKCc9JylcbiAgaWYgKHZhbGlkTGVuID09PSAtMSkgdmFsaWRMZW4gPSBsZW5cblxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gdmFsaWRMZW4gPT09IGxlblxuICAgID8gMFxuICAgIDogNCAtICh2YWxpZExlbiAlIDQpXG5cbiAgcmV0dXJuIFt2YWxpZExlbiwgcGxhY2VIb2xkZXJzTGVuXVxufVxuXG4vLyBiYXNlNjQgaXMgNC8zICsgdXAgdG8gdHdvIGNoYXJhY3RlcnMgb2YgdGhlIG9yaWdpbmFsIGRhdGFcbmZ1bmN0aW9uIGJ5dGVMZW5ndGggKGI2NCkge1xuICB2YXIgbGVucyA9IGdldExlbnMoYjY0KVxuICB2YXIgdmFsaWRMZW4gPSBsZW5zWzBdXG4gIHZhciBwbGFjZUhvbGRlcnNMZW4gPSBsZW5zWzFdXG4gIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlblxufVxuXG5mdW5jdGlvbiBfYnl0ZUxlbmd0aCAoYjY0LCB2YWxpZExlbiwgcGxhY2VIb2xkZXJzTGVuKSB7XG4gIHJldHVybiAoKHZhbGlkTGVuICsgcGxhY2VIb2xkZXJzTGVuKSAqIDMgLyA0KSAtIHBsYWNlSG9sZGVyc0xlblxufVxuXG5mdW5jdGlvbiB0b0J5dGVBcnJheSAoYjY0KSB7XG4gIHZhciB0bXBcbiAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NClcbiAgdmFyIHZhbGlkTGVuID0gbGVuc1swXVxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXVxuXG4gIHZhciBhcnIgPSBuZXcgQXJyKF9ieXRlTGVuZ3RoKGI2NCwgdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbikpXG5cbiAgdmFyIGN1ckJ5dGUgPSAwXG5cbiAgLy8gaWYgdGhlcmUgYXJlIHBsYWNlaG9sZGVycywgb25seSBnZXQgdXAgdG8gdGhlIGxhc3QgY29tcGxldGUgNCBjaGFyc1xuICB2YXIgbGVuID0gcGxhY2VIb2xkZXJzTGVuID4gMFxuICAgID8gdmFsaWRMZW4gLSA0XG4gICAgOiB2YWxpZExlblxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDQpIHtcbiAgICB0bXAgPVxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMTgpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA8PCAxMikgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMildIDw8IDYpIHxcbiAgICAgIHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMyldXG4gICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDE2KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gOCkgJiAweEZGXG4gICAgYXJyW2N1ckJ5dGUrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICBpZiAocGxhY2VIb2xkZXJzTGVuID09PSAyKSB7XG4gICAgdG1wID1cbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDIpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA+PiA0KVxuICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRlxuICB9XG5cbiAgaWYgKHBsYWNlSG9sZGVyc0xlbiA9PT0gMSkge1xuICAgIHRtcCA9XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAxMCkgfFxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpICsgMSldIDw8IDQpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA+PiAyKVxuICAgIGFycltjdXJCeXRlKytdID0gKHRtcCA+PiA4KSAmIDB4RkZcbiAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBhcnJcbn1cblxuZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcbiAgcmV0dXJuIGxvb2t1cFtudW0gPj4gMTggJiAweDNGXSArXG4gICAgbG9va3VwW251bSA+PiAxMiAmIDB4M0ZdICtcbiAgICBsb29rdXBbbnVtID4+IDYgJiAweDNGXSArXG4gICAgbG9va3VwW251bSAmIDB4M0ZdXG59XG5cbmZ1bmN0aW9uIGVuY29kZUNodW5rICh1aW50OCwgc3RhcnQsIGVuZCkge1xuICB2YXIgdG1wXG4gIHZhciBvdXRwdXQgPSBbXVxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gMykge1xuICAgIHRtcCA9XG4gICAgICAoKHVpbnQ4W2ldIDw8IDE2KSAmIDB4RkYwMDAwKSArXG4gICAgICAoKHVpbnQ4W2kgKyAxXSA8PCA4KSAmIDB4RkYwMCkgK1xuICAgICAgKHVpbnQ4W2kgKyAyXSAmIDB4RkYpXG4gICAgb3V0cHV0LnB1c2godHJpcGxldFRvQmFzZTY0KHRtcCkpXG4gIH1cbiAgcmV0dXJuIG91dHB1dC5qb2luKCcnKVxufVxuXG5mdW5jdGlvbiBmcm9tQnl0ZUFycmF5ICh1aW50OCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW4gPSB1aW50OC5sZW5ndGhcbiAgdmFyIGV4dHJhQnl0ZXMgPSBsZW4gJSAzIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG4gIHZhciBwYXJ0cyA9IFtdXG4gIHZhciBtYXhDaHVua0xlbmd0aCA9IDE2MzgzIC8vIG11c3QgYmUgbXVsdGlwbGUgb2YgM1xuXG4gIC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcbiAgZm9yICh2YXIgaSA9IDAsIGxlbjIgPSBsZW4gLSBleHRyYUJ5dGVzOyBpIDwgbGVuMjsgaSArPSBtYXhDaHVua0xlbmd0aCkge1xuICAgIHBhcnRzLnB1c2goZW5jb2RlQ2h1bmsoXG4gICAgICB1aW50OCwgaSwgKGkgKyBtYXhDaHVua0xlbmd0aCkgPiBsZW4yID8gbGVuMiA6IChpICsgbWF4Q2h1bmtMZW5ndGgpXG4gICAgKSlcbiAgfVxuXG4gIC8vIHBhZCB0aGUgZW5kIHdpdGggemVyb3MsIGJ1dCBtYWtlIHN1cmUgdG8gbm90IGZvcmdldCB0aGUgZXh0cmEgYnl0ZXNcbiAgaWYgKGV4dHJhQnl0ZXMgPT09IDEpIHtcbiAgICB0bXAgPSB1aW50OFtsZW4gLSAxXVxuICAgIHBhcnRzLnB1c2goXG4gICAgICBsb29rdXBbdG1wID4+IDJdICtcbiAgICAgIGxvb2t1cFsodG1wIDw8IDQpICYgMHgzRl0gK1xuICAgICAgJz09J1xuICAgIClcbiAgfSBlbHNlIGlmIChleHRyYUJ5dGVzID09PSAyKSB7XG4gICAgdG1wID0gKHVpbnQ4W2xlbiAtIDJdIDw8IDgpICsgdWludDhbbGVuIC0gMV1cbiAgICBwYXJ0cy5wdXNoKFxuICAgICAgbG9va3VwW3RtcCA+PiAxMF0gK1xuICAgICAgbG9va3VwWyh0bXAgPj4gNCkgJiAweDNGXSArXG4gICAgICBsb29rdXBbKHRtcCA8PCAyKSAmIDB4M0ZdICtcbiAgICAgICc9J1xuICAgIClcbiAgfVxuXG4gIHJldHVybiBwYXJ0cy5qb2luKCcnKVxufVxuIiwiIiwiLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8ZmVyb3NzQGZlcm9zcy5vcmc+IDxodHRwOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuLyogZXNsaW50LWRpc2FibGUgbm8tcHJvdG8gKi9cblxuJ3VzZSBzdHJpY3QnXG5cbnZhciBiYXNlNjQgPSByZXF1aXJlKCdiYXNlNjQtanMnKVxudmFyIGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0JylcbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnaXNhcnJheScpXG5cbmV4cG9ydHMuQnVmZmVyID0gQnVmZmVyXG5leHBvcnRzLlNsb3dCdWZmZXIgPSBTbG93QnVmZmVyXG5leHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTID0gNTBcblxuLyoqXG4gKiBJZiBgQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRgOlxuICogICA9PT0gdHJ1ZSAgICBVc2UgVWludDhBcnJheSBpbXBsZW1lbnRhdGlvbiAoZmFzdGVzdClcbiAqICAgPT09IGZhbHNlICAgVXNlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiAobW9zdCBjb21wYXRpYmxlLCBldmVuIElFNilcbiAqXG4gKiBCcm93c2VycyB0aGF0IHN1cHBvcnQgdHlwZWQgYXJyYXlzIGFyZSBJRSAxMCssIEZpcmVmb3ggNCssIENocm9tZSA3KywgU2FmYXJpIDUuMSssXG4gKiBPcGVyYSAxMS42KywgaU9TIDQuMisuXG4gKlxuICogRHVlIHRvIHZhcmlvdXMgYnJvd3NlciBidWdzLCBzb21ldGltZXMgdGhlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiB3aWxsIGJlIHVzZWQgZXZlblxuICogd2hlbiB0aGUgYnJvd3NlciBzdXBwb3J0cyB0eXBlZCBhcnJheXMuXG4gKlxuICogTm90ZTpcbiAqXG4gKiAgIC0gRmlyZWZveCA0LTI5IGxhY2tzIHN1cHBvcnQgZm9yIGFkZGluZyBuZXcgcHJvcGVydGllcyB0byBgVWludDhBcnJheWAgaW5zdGFuY2VzLFxuICogICAgIFNlZTogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9Njk1NDM4LlxuICpcbiAqICAgLSBDaHJvbWUgOS0xMCBpcyBtaXNzaW5nIHRoZSBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uLlxuICpcbiAqICAgLSBJRTEwIGhhcyBhIGJyb2tlbiBgVHlwZWRBcnJheS5wcm90b3R5cGUuc3ViYXJyYXlgIGZ1bmN0aW9uIHdoaWNoIHJldHVybnMgYXJyYXlzIG9mXG4gKiAgICAgaW5jb3JyZWN0IGxlbmd0aCBpbiBzb21lIHNpdHVhdGlvbnMuXG5cbiAqIFdlIGRldGVjdCB0aGVzZSBidWdneSBicm93c2VycyBhbmQgc2V0IGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGAgdG8gYGZhbHNlYCBzbyB0aGV5XG4gKiBnZXQgdGhlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiwgd2hpY2ggaXMgc2xvd2VyIGJ1dCBiZWhhdmVzIGNvcnJlY3RseS5cbiAqL1xuQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgPSBnbG9iYWwuVFlQRURfQVJSQVlfU1VQUE9SVCAhPT0gdW5kZWZpbmVkXG4gID8gZ2xvYmFsLlRZUEVEX0FSUkFZX1NVUFBPUlRcbiAgOiB0eXBlZEFycmF5U3VwcG9ydCgpXG5cbi8qXG4gKiBFeHBvcnQga01heExlbmd0aCBhZnRlciB0eXBlZCBhcnJheSBzdXBwb3J0IGlzIGRldGVybWluZWQuXG4gKi9cbmV4cG9ydHMua01heExlbmd0aCA9IGtNYXhMZW5ndGgoKVxuXG5mdW5jdGlvbiB0eXBlZEFycmF5U3VwcG9ydCAoKSB7XG4gIHRyeSB7XG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KDEpXG4gICAgYXJyLl9fcHJvdG9fXyA9IHtfX3Byb3RvX186IFVpbnQ4QXJyYXkucHJvdG90eXBlLCBmb286IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH19XG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDIgJiYgLy8gdHlwZWQgYXJyYXkgaW5zdGFuY2VzIGNhbiBiZSBhdWdtZW50ZWRcbiAgICAgICAgdHlwZW9mIGFyci5zdWJhcnJheSA9PT0gJ2Z1bmN0aW9uJyAmJiAvLyBjaHJvbWUgOS0xMCBsYWNrIGBzdWJhcnJheWBcbiAgICAgICAgYXJyLnN1YmFycmF5KDEsIDEpLmJ5dGVMZW5ndGggPT09IDAgLy8gaWUxMCBoYXMgYnJva2VuIGBzdWJhcnJheWBcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbmZ1bmN0aW9uIGtNYXhMZW5ndGggKCkge1xuICByZXR1cm4gQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRcbiAgICA/IDB4N2ZmZmZmZmZcbiAgICA6IDB4M2ZmZmZmZmZcbn1cblxuZnVuY3Rpb24gY3JlYXRlQnVmZmVyICh0aGF0LCBsZW5ndGgpIHtcbiAgaWYgKGtNYXhMZW5ndGgoKSA8IGxlbmd0aCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbnZhbGlkIHR5cGVkIGFycmF5IGxlbmd0aCcpXG4gIH1cbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UsIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgdGhhdCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aClcbiAgICB0aGF0Ll9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIGFuIG9iamVjdCBpbnN0YW5jZSBvZiB0aGUgQnVmZmVyIGNsYXNzXG4gICAgaWYgKHRoYXQgPT09IG51bGwpIHtcbiAgICAgIHRoYXQgPSBuZXcgQnVmZmVyKGxlbmd0aClcbiAgICB9XG4gICAgdGhhdC5sZW5ndGggPSBsZW5ndGhcbiAgfVxuXG4gIHJldHVybiB0aGF0XG59XG5cbi8qKlxuICogVGhlIEJ1ZmZlciBjb25zdHJ1Y3RvciByZXR1cm5zIGluc3RhbmNlcyBvZiBgVWludDhBcnJheWAgdGhhdCBoYXZlIHRoZWlyXG4gKiBwcm90b3R5cGUgY2hhbmdlZCB0byBgQnVmZmVyLnByb3RvdHlwZWAuIEZ1cnRoZXJtb3JlLCBgQnVmZmVyYCBpcyBhIHN1YmNsYXNzIG9mXG4gKiBgVWludDhBcnJheWAsIHNvIHRoZSByZXR1cm5lZCBpbnN0YW5jZXMgd2lsbCBoYXZlIGFsbCB0aGUgbm9kZSBgQnVmZmVyYCBtZXRob2RzXG4gKiBhbmQgdGhlIGBVaW50OEFycmF5YCBtZXRob2RzLiBTcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdFxuICogcmV0dXJucyBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBUaGUgYFVpbnQ4QXJyYXlgIHByb3RvdHlwZSByZW1haW5zIHVubW9kaWZpZWQuXG4gKi9cblxuZnVuY3Rpb24gQnVmZmVyIChhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUICYmICEodGhpcyBpbnN0YW5jZW9mIEJ1ZmZlcikpIHtcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcihhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIC8vIENvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICBpZiAodHlwZW9mIGVuY29kaW5nT3JPZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdJZiBlbmNvZGluZyBpcyBzcGVjaWZpZWQgdGhlbiB0aGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZydcbiAgICAgIClcbiAgICB9XG4gICAgcmV0dXJuIGFsbG9jVW5zYWZlKHRoaXMsIGFyZylcbiAgfVxuICByZXR1cm4gZnJvbSh0aGlzLCBhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnBvb2xTaXplID0gODE5MiAvLyBub3QgdXNlZCBieSB0aGlzIGltcGxlbWVudGF0aW9uXG5cbi8vIFRPRE86IExlZ2FjeSwgbm90IG5lZWRlZCBhbnltb3JlLiBSZW1vdmUgaW4gbmV4dCBtYWpvciB2ZXJzaW9uLlxuQnVmZmVyLl9hdWdtZW50ID0gZnVuY3Rpb24gKGFycikge1xuICBhcnIuX19wcm90b19fID0gQnVmZmVyLnByb3RvdHlwZVxuICByZXR1cm4gYXJyXG59XG5cbmZ1bmN0aW9uIGZyb20gKHRoYXQsIHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcInZhbHVlXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgYSBudW1iZXInKVxuICB9XG5cbiAgaWYgKHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcgJiYgdmFsdWUgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgIHJldHVybiBmcm9tQXJyYXlCdWZmZXIodGhhdCwgdmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIGZyb21TdHJpbmcodGhhdCwgdmFsdWUsIGVuY29kaW5nT3JPZmZzZXQpXG4gIH1cblxuICByZXR1cm4gZnJvbU9iamVjdCh0aGF0LCB2YWx1ZSlcbn1cblxuLyoqXG4gKiBGdW5jdGlvbmFsbHkgZXF1aXZhbGVudCB0byBCdWZmZXIoYXJnLCBlbmNvZGluZykgYnV0IHRocm93cyBhIFR5cGVFcnJvclxuICogaWYgdmFsdWUgaXMgYSBudW1iZXIuXG4gKiBCdWZmZXIuZnJvbShzdHJbLCBlbmNvZGluZ10pXG4gKiBCdWZmZXIuZnJvbShhcnJheSlcbiAqIEJ1ZmZlci5mcm9tKGJ1ZmZlcilcbiAqIEJ1ZmZlci5mcm9tKGFycmF5QnVmZmVyWywgYnl0ZU9mZnNldFssIGxlbmd0aF1dKVxuICoqL1xuQnVmZmVyLmZyb20gPSBmdW5jdGlvbiAodmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gZnJvbShudWxsLCB2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxufVxuXG5pZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgQnVmZmVyLnByb3RvdHlwZS5fX3Byb3RvX18gPSBVaW50OEFycmF5LnByb3RvdHlwZVxuICBCdWZmZXIuX19wcm90b19fID0gVWludDhBcnJheVxuICBpZiAodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLnNwZWNpZXMgJiZcbiAgICAgIEJ1ZmZlcltTeW1ib2wuc3BlY2llc10gPT09IEJ1ZmZlcikge1xuICAgIC8vIEZpeCBzdWJhcnJheSgpIGluIEVTMjAxNi4gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlci9wdWxsLzk3XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEJ1ZmZlciwgU3ltYm9sLnNwZWNpZXMsIHtcbiAgICAgIHZhbHVlOiBudWxsLFxuICAgICAgY29uZmlndXJhYmxlOiB0cnVlXG4gICAgfSlcbiAgfVxufVxuXG5mdW5jdGlvbiBhc3NlcnRTaXplIChzaXplKSB7XG4gIGlmICh0eXBlb2Ygc2l6ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcInNpemVcIiBhcmd1bWVudCBtdXN0IGJlIGEgbnVtYmVyJylcbiAgfSBlbHNlIGlmIChzaXplIDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcInNpemVcIiBhcmd1bWVudCBtdXN0IG5vdCBiZSBuZWdhdGl2ZScpXG4gIH1cbn1cblxuZnVuY3Rpb24gYWxsb2MgKHRoYXQsIHNpemUsIGZpbGwsIGVuY29kaW5nKSB7XG4gIGFzc2VydFNpemUoc2l6ZSlcbiAgaWYgKHNpemUgPD0gMCkge1xuICAgIHJldHVybiBjcmVhdGVCdWZmZXIodGhhdCwgc2l6ZSlcbiAgfVxuICBpZiAoZmlsbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gT25seSBwYXkgYXR0ZW50aW9uIHRvIGVuY29kaW5nIGlmIGl0J3MgYSBzdHJpbmcuIFRoaXNcbiAgICAvLyBwcmV2ZW50cyBhY2NpZGVudGFsbHkgc2VuZGluZyBpbiBhIG51bWJlciB0aGF0IHdvdWxkXG4gICAgLy8gYmUgaW50ZXJwcmV0dGVkIGFzIGEgc3RhcnQgb2Zmc2V0LlxuICAgIHJldHVybiB0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnXG4gICAgICA/IGNyZWF0ZUJ1ZmZlcih0aGF0LCBzaXplKS5maWxsKGZpbGwsIGVuY29kaW5nKVxuICAgICAgOiBjcmVhdGVCdWZmZXIodGhhdCwgc2l6ZSkuZmlsbChmaWxsKVxuICB9XG4gIHJldHVybiBjcmVhdGVCdWZmZXIodGhhdCwgc2l6ZSlcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKiBhbGxvYyhzaXplWywgZmlsbFssIGVuY29kaW5nXV0pXG4gKiovXG5CdWZmZXIuYWxsb2MgPSBmdW5jdGlvbiAoc2l6ZSwgZmlsbCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGFsbG9jKG51bGwsIHNpemUsIGZpbGwsIGVuY29kaW5nKVxufVxuXG5mdW5jdGlvbiBhbGxvY1Vuc2FmZSAodGhhdCwgc2l6ZSkge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIHRoYXQgPSBjcmVhdGVCdWZmZXIodGhhdCwgc2l6ZSA8IDAgPyAwIDogY2hlY2tlZChzaXplKSB8IDApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpemU7ICsraSkge1xuICAgICAgdGhhdFtpXSA9IDBcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuLyoqXG4gKiBFcXVpdmFsZW50IHRvIEJ1ZmZlcihudW0pLCBieSBkZWZhdWx0IGNyZWF0ZXMgYSBub24temVyby1maWxsZWQgQnVmZmVyIGluc3RhbmNlLlxuICogKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZSA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIHJldHVybiBhbGxvY1Vuc2FmZShudWxsLCBzaXplKVxufVxuLyoqXG4gKiBFcXVpdmFsZW50IHRvIFNsb3dCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqL1xuQnVmZmVyLmFsbG9jVW5zYWZlU2xvdyA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIHJldHVybiBhbGxvY1Vuc2FmZShudWxsLCBzaXplKVxufVxuXG5mdW5jdGlvbiBmcm9tU3RyaW5nICh0aGF0LCBzdHJpbmcsIGVuY29kaW5nKSB7XG4gIGlmICh0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnIHx8IGVuY29kaW5nID09PSAnJykge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gIH1cblxuICBpZiAoIUJ1ZmZlci5pc0VuY29kaW5nKGVuY29kaW5nKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiZW5jb2RpbmdcIiBtdXN0IGJlIGEgdmFsaWQgc3RyaW5nIGVuY29kaW5nJylcbiAgfVxuXG4gIHZhciBsZW5ndGggPSBieXRlTGVuZ3RoKHN0cmluZywgZW5jb2RpbmcpIHwgMFxuICB0aGF0ID0gY3JlYXRlQnVmZmVyKHRoYXQsIGxlbmd0aClcblxuICB2YXIgYWN0dWFsID0gdGhhdC53cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuXG4gIGlmIChhY3R1YWwgIT09IGxlbmd0aCkge1xuICAgIC8vIFdyaXRpbmcgYSBoZXggc3RyaW5nLCBmb3IgZXhhbXBsZSwgdGhhdCBjb250YWlucyBpbnZhbGlkIGNoYXJhY3RlcnMgd2lsbFxuICAgIC8vIGNhdXNlIGV2ZXJ5dGhpbmcgYWZ0ZXIgdGhlIGZpcnN0IGludmFsaWQgY2hhcmFjdGVyIHRvIGJlIGlnbm9yZWQuIChlLmcuXG4gICAgLy8gJ2FieHhjZCcgd2lsbCBiZSB0cmVhdGVkIGFzICdhYicpXG4gICAgdGhhdCA9IHRoYXQuc2xpY2UoMCwgYWN0dWFsKVxuICB9XG5cbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gZnJvbUFycmF5TGlrZSAodGhhdCwgYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChhcnJheS5sZW5ndGgpIHwgMFxuICB0aGF0ID0gY3JlYXRlQnVmZmVyKHRoYXQsIGxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAodGhhdCwgYXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aCkge1xuICBhcnJheS5ieXRlTGVuZ3RoIC8vIHRoaXMgdGhyb3dzIGlmIGBhcnJheWAgaXMgbm90IGEgdmFsaWQgQXJyYXlCdWZmZXJcblxuICBpZiAoYnl0ZU9mZnNldCA8IDAgfHwgYXJyYXkuYnl0ZUxlbmd0aCA8IGJ5dGVPZmZzZXQpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXFwnb2Zmc2V0XFwnIGlzIG91dCBvZiBib3VuZHMnKVxuICB9XG5cbiAgaWYgKGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0ICsgKGxlbmd0aCB8fCAwKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcXCdsZW5ndGhcXCcgaXMgb3V0IG9mIGJvdW5kcycpXG4gIH1cblxuICBpZiAoYnl0ZU9mZnNldCA9PT0gdW5kZWZpbmVkICYmIGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYXJyYXkgPSBuZXcgVWludDhBcnJheShhcnJheSlcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXksIGJ5dGVPZmZzZXQpXG4gIH0gZWxzZSB7XG4gICAgYXJyYXkgPSBuZXcgVWludDhBcnJheShhcnJheSwgYnl0ZU9mZnNldCwgbGVuZ3RoKVxuICB9XG5cbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UsIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgdGhhdCA9IGFycmF5XG4gICAgdGhhdC5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIH0gZWxzZSB7XG4gICAgLy8gRmFsbGJhY2s6IFJldHVybiBhbiBvYmplY3QgaW5zdGFuY2Ugb2YgdGhlIEJ1ZmZlciBjbGFzc1xuICAgIHRoYXQgPSBmcm9tQXJyYXlMaWtlKHRoYXQsIGFycmF5KVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21PYmplY3QgKHRoYXQsIG9iaikge1xuICBpZiAoQnVmZmVyLmlzQnVmZmVyKG9iaikpIHtcbiAgICB2YXIgbGVuID0gY2hlY2tlZChvYmoubGVuZ3RoKSB8IDBcbiAgICB0aGF0ID0gY3JlYXRlQnVmZmVyKHRoYXQsIGxlbilcblxuICAgIGlmICh0aGF0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoYXRcbiAgICB9XG5cbiAgICBvYmouY29weSh0aGF0LCAwLCAwLCBsZW4pXG4gICAgcmV0dXJuIHRoYXRcbiAgfVxuXG4gIGlmIChvYmopIHtcbiAgICBpZiAoKHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICAgICAgb2JqLmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB8fCAnbGVuZ3RoJyBpbiBvYmopIHtcbiAgICAgIGlmICh0eXBlb2Ygb2JqLmxlbmd0aCAhPT0gJ251bWJlcicgfHwgaXNuYW4ob2JqLmxlbmd0aCkpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUJ1ZmZlcih0aGF0LCAwKVxuICAgICAgfVxuICAgICAgcmV0dXJuIGZyb21BcnJheUxpa2UodGhhdCwgb2JqKVxuICAgIH1cblxuICAgIGlmIChvYmoudHlwZSA9PT0gJ0J1ZmZlcicgJiYgaXNBcnJheShvYmouZGF0YSkpIHtcbiAgICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKHRoYXQsIG9iai5kYXRhKVxuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBzdHJpbmcsIEJ1ZmZlciwgQXJyYXlCdWZmZXIsIEFycmF5LCBvciBhcnJheS1saWtlIG9iamVjdC4nKVxufVxuXG5mdW5jdGlvbiBjaGVja2VkIChsZW5ndGgpIHtcbiAgLy8gTm90ZTogY2Fubm90IHVzZSBgbGVuZ3RoIDwga01heExlbmd0aCgpYCBoZXJlIGJlY2F1c2UgdGhhdCBmYWlscyB3aGVuXG4gIC8vIGxlbmd0aCBpcyBOYU4gKHdoaWNoIGlzIG90aGVyd2lzZSBjb2VyY2VkIHRvIHplcm8uKVxuICBpZiAobGVuZ3RoID49IGtNYXhMZW5ndGgoKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICdzaXplOiAweCcgKyBrTWF4TGVuZ3RoKCkudG9TdHJpbmcoMTYpICsgJyBieXRlcycpXG4gIH1cbiAgcmV0dXJuIGxlbmd0aCB8IDBcbn1cblxuZnVuY3Rpb24gU2xvd0J1ZmZlciAobGVuZ3RoKSB7XG4gIGlmICgrbGVuZ3RoICE9IGxlbmd0aCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGVxZXFlcVxuICAgIGxlbmd0aCA9IDBcbiAgfVxuICByZXR1cm4gQnVmZmVyLmFsbG9jKCtsZW5ndGgpXG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIGlzQnVmZmVyIChiKSB7XG4gIHJldHVybiAhIShiICE9IG51bGwgJiYgYi5faXNCdWZmZXIpXG59XG5cbkJ1ZmZlci5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAoYSwgYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihhKSB8fCAhQnVmZmVyLmlzQnVmZmVyKGIpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnRzIG11c3QgYmUgQnVmZmVycycpXG4gIH1cblxuICBpZiAoYSA9PT0gYikgcmV0dXJuIDBcblxuICB2YXIgeCA9IGEubGVuZ3RoXG4gIHZhciB5ID0gYi5sZW5ndGhcblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gTWF0aC5taW4oeCwgeSk7IGkgPCBsZW47ICsraSkge1xuICAgIGlmIChhW2ldICE9PSBiW2ldKSB7XG4gICAgICB4ID0gYVtpXVxuICAgICAgeSA9IGJbaV1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG5CdWZmZXIuaXNFbmNvZGluZyA9IGZ1bmN0aW9uIGlzRW5jb2RpbmcgKGVuY29kaW5nKSB7XG4gIHN3aXRjaCAoU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5CdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gY29uY2F0IChsaXN0LCBsZW5ndGgpIHtcbiAgaWYgKCFpc0FycmF5KGxpc3QpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJylcbiAgfVxuXG4gIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBCdWZmZXIuYWxsb2MoMClcbiAgfVxuXG4gIHZhciBpXG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGxlbmd0aCA9IDBcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7ICsraSkge1xuICAgICAgbGVuZ3RoICs9IGxpc3RbaV0ubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgdmFyIGJ1ZmZlciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZShsZW5ndGgpXG4gIHZhciBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIGJ1ZiA9IGxpc3RbaV1cbiAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihidWYpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImxpc3RcIiBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMnKVxuICAgIH1cbiAgICBidWYuY29weShidWZmZXIsIHBvcylcbiAgICBwb3MgKz0gYnVmLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZmZXJcbn1cblxuZnVuY3Rpb24gYnl0ZUxlbmd0aCAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHN0cmluZykpIHtcbiAgICByZXR1cm4gc3RyaW5nLmxlbmd0aFxuICB9XG4gIGlmICh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZiBBcnJheUJ1ZmZlci5pc1ZpZXcgPT09ICdmdW5jdGlvbicgJiZcbiAgICAgIChBcnJheUJ1ZmZlci5pc1ZpZXcoc3RyaW5nKSB8fCBzdHJpbmcgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikpIHtcbiAgICByZXR1cm4gc3RyaW5nLmJ5dGVMZW5ndGhcbiAgfVxuICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHtcbiAgICBzdHJpbmcgPSAnJyArIHN0cmluZ1xuICB9XG5cbiAgdmFyIGxlbiA9IHN0cmluZy5sZW5ndGhcbiAgaWYgKGxlbiA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBVc2UgYSBmb3IgbG9vcCB0byBhdm9pZCByZWN1cnNpb25cbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gbGVuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiBsZW4gKiAyXG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gbGVuID4+PiAxXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGggLy8gYXNzdW1lIHV0ZjhcbiAgICAgICAgZW5jb2RpbmcgPSAoJycgKyBlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuXG5mdW5jdGlvbiBzbG93VG9TdHJpbmcgKGVuY29kaW5nLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG5cbiAgLy8gTm8gbmVlZCB0byB2ZXJpZnkgdGhhdCBcInRoaXMubGVuZ3RoIDw9IE1BWF9VSU5UMzJcIiBzaW5jZSBpdCdzIGEgcmVhZC1vbmx5XG4gIC8vIHByb3BlcnR5IG9mIGEgdHlwZWQgYXJyYXkuXG5cbiAgLy8gVGhpcyBiZWhhdmVzIG5laXRoZXIgbGlrZSBTdHJpbmcgbm9yIFVpbnQ4QXJyYXkgaW4gdGhhdCB3ZSBzZXQgc3RhcnQvZW5kXG4gIC8vIHRvIHRoZWlyIHVwcGVyL2xvd2VyIGJvdW5kcyBpZiB0aGUgdmFsdWUgcGFzc2VkIGlzIG91dCBvZiByYW5nZS5cbiAgLy8gdW5kZWZpbmVkIGlzIGhhbmRsZWQgc3BlY2lhbGx5IGFzIHBlciBFQ01BLTI2MiA2dGggRWRpdGlvbixcbiAgLy8gU2VjdGlvbiAxMy4zLjMuNyBSdW50aW1lIFNlbWFudGljczogS2V5ZWRCaW5kaW5nSW5pdGlhbGl6YXRpb24uXG4gIGlmIChzdGFydCA9PT0gdW5kZWZpbmVkIHx8IHN0YXJ0IDwgMCkge1xuICAgIHN0YXJ0ID0gMFxuICB9XG4gIC8vIFJldHVybiBlYXJseSBpZiBzdGFydCA+IHRoaXMubGVuZ3RoLiBEb25lIGhlcmUgdG8gcHJldmVudCBwb3RlbnRpYWwgdWludDMyXG4gIC8vIGNvZXJjaW9uIGZhaWwgYmVsb3cuXG4gIGlmIChzdGFydCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICBpZiAoZW5kID09PSB1bmRlZmluZWQgfHwgZW5kID4gdGhpcy5sZW5ndGgpIHtcbiAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICB9XG5cbiAgaWYgKGVuZCA8PSAwKSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICAvLyBGb3JjZSBjb2Vyc2lvbiB0byB1aW50MzIuIFRoaXMgd2lsbCBhbHNvIGNvZXJjZSBmYWxzZXkvTmFOIHZhbHVlcyB0byAwLlxuICBlbmQgPj4+PSAwXG4gIHN0YXJ0ID4+Pj0gMFxuXG4gIGlmIChlbmQgPD0gc3RhcnQpIHtcbiAgICByZXR1cm4gJydcbiAgfVxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGxhdGluMVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIHJldHVybiBiYXNlNjRTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdXRmMTZsZVNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9IChlbmNvZGluZyArICcnKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG4vLyBUaGUgcHJvcGVydHkgaXMgdXNlZCBieSBgQnVmZmVyLmlzQnVmZmVyYCBhbmQgYGlzLWJ1ZmZlcmAgKGluIFNhZmFyaSA1LTcpIHRvIGRldGVjdFxuLy8gQnVmZmVyIGluc3RhbmNlcy5cbkJ1ZmZlci5wcm90b3R5cGUuX2lzQnVmZmVyID0gdHJ1ZVxuXG5mdW5jdGlvbiBzd2FwIChiLCBuLCBtKSB7XG4gIHZhciBpID0gYltuXVxuICBiW25dID0gYlttXVxuICBiW21dID0gaVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXAxNiA9IGZ1bmN0aW9uIHN3YXAxNiAoKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgMiAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgMTYtYml0cycpXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gMikge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDEpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMzIgPSBmdW5jdGlvbiBzd2FwMzIgKCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbiAlIDQgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQnVmZmVyIHNpemUgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDMyLWJpdHMnKVxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDQpIHtcbiAgICBzd2FwKHRoaXMsIGksIGkgKyAzKVxuICAgIHN3YXAodGhpcywgaSArIDEsIGkgKyAyKVxuICB9XG4gIHJldHVybiB0aGlzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc3dhcDY0ID0gZnVuY3Rpb24gc3dhcDY0ICgpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSA4ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA2NC1iaXRzJylcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSA4KSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgNylcbiAgICBzd2FwKHRoaXMsIGkgKyAxLCBpICsgNilcbiAgICBzd2FwKHRoaXMsIGkgKyAyLCBpICsgNSlcbiAgICBzd2FwKHRoaXMsIGkgKyAzLCBpICsgNClcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcgKCkge1xuICB2YXIgbGVuZ3RoID0gdGhpcy5sZW5ndGggfCAwXG4gIGlmIChsZW5ndGggPT09IDApIHJldHVybiAnJ1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHV0ZjhTbGljZSh0aGlzLCAwLCBsZW5ndGgpXG4gIHJldHVybiBzbG93VG9TdHJpbmcuYXBwbHkodGhpcywgYXJndW1lbnRzKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uIGVxdWFscyAoYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG4gIGlmICh0aGlzID09PSBiKSByZXR1cm4gdHJ1ZVxuICByZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcywgYikgPT09IDBcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0ID0gZnVuY3Rpb24gaW5zcGVjdCAoKSB7XG4gIHZhciBzdHIgPSAnJ1xuICB2YXIgbWF4ID0gZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFU1xuICBpZiAodGhpcy5sZW5ndGggPiAwKSB7XG4gICAgc3RyID0gdGhpcy50b1N0cmluZygnaGV4JywgMCwgbWF4KS5tYXRjaCgvLnsyfS9nKS5qb2luKCcgJylcbiAgICBpZiAodGhpcy5sZW5ndGggPiBtYXgpIHN0ciArPSAnIC4uLiAnXG4gIH1cbiAgcmV0dXJuICc8QnVmZmVyICcgKyBzdHIgKyAnPidcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZSAodGFyZ2V0LCBzdGFydCwgZW5kLCB0aGlzU3RhcnQsIHRoaXNFbmQpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodGFyZ2V0KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICB9XG5cbiAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQpIHtcbiAgICBzdGFydCA9IDBcbiAgfVxuICBpZiAoZW5kID09PSB1bmRlZmluZWQpIHtcbiAgICBlbmQgPSB0YXJnZXQgPyB0YXJnZXQubGVuZ3RoIDogMFxuICB9XG4gIGlmICh0aGlzU3RhcnQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRoaXNTdGFydCA9IDBcbiAgfVxuICBpZiAodGhpc0VuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgdGhpc0VuZCA9IHRoaXMubGVuZ3RoXG4gIH1cblxuICBpZiAoc3RhcnQgPCAwIHx8IGVuZCA+IHRhcmdldC5sZW5ndGggfHwgdGhpc1N0YXJ0IDwgMCB8fCB0aGlzRW5kID4gdGhpcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb3V0IG9mIHJhbmdlIGluZGV4JylcbiAgfVxuXG4gIGlmICh0aGlzU3RhcnQgPj0gdGhpc0VuZCAmJiBzdGFydCA+PSBlbmQpIHtcbiAgICByZXR1cm4gMFxuICB9XG4gIGlmICh0aGlzU3RhcnQgPj0gdGhpc0VuZCkge1xuICAgIHJldHVybiAtMVxuICB9XG4gIGlmIChzdGFydCA+PSBlbmQpIHtcbiAgICByZXR1cm4gMVxuICB9XG5cbiAgc3RhcnQgPj4+PSAwXG4gIGVuZCA+Pj49IDBcbiAgdGhpc1N0YXJ0ID4+Pj0gMFxuICB0aGlzRW5kID4+Pj0gMFxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQpIHJldHVybiAwXG5cbiAgdmFyIHggPSB0aGlzRW5kIC0gdGhpc1N0YXJ0XG4gIHZhciB5ID0gZW5kIC0gc3RhcnRcbiAgdmFyIGxlbiA9IE1hdGgubWluKHgsIHkpXG5cbiAgdmFyIHRoaXNDb3B5ID0gdGhpcy5zbGljZSh0aGlzU3RhcnQsIHRoaXNFbmQpXG4gIHZhciB0YXJnZXRDb3B5ID0gdGFyZ2V0LnNsaWNlKHN0YXJ0LCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgIGlmICh0aGlzQ29weVtpXSAhPT0gdGFyZ2V0Q29weVtpXSkge1xuICAgICAgeCA9IHRoaXNDb3B5W2ldXG4gICAgICB5ID0gdGFyZ2V0Q29weVtpXVxuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cblxuICBpZiAoeCA8IHkpIHJldHVybiAtMVxuICBpZiAoeSA8IHgpIHJldHVybiAxXG4gIHJldHVybiAwXG59XG5cbi8vIEZpbmRzIGVpdGhlciB0aGUgZmlyc3QgaW5kZXggb2YgYHZhbGAgaW4gYGJ1ZmZlcmAgYXQgb2Zmc2V0ID49IGBieXRlT2Zmc2V0YCxcbi8vIE9SIHRoZSBsYXN0IGluZGV4IG9mIGB2YWxgIGluIGBidWZmZXJgIGF0IG9mZnNldCA8PSBgYnl0ZU9mZnNldGAuXG4vL1xuLy8gQXJndW1lbnRzOlxuLy8gLSBidWZmZXIgLSBhIEJ1ZmZlciB0byBzZWFyY2hcbi8vIC0gdmFsIC0gYSBzdHJpbmcsIEJ1ZmZlciwgb3IgbnVtYmVyXG4vLyAtIGJ5dGVPZmZzZXQgLSBhbiBpbmRleCBpbnRvIGBidWZmZXJgOyB3aWxsIGJlIGNsYW1wZWQgdG8gYW4gaW50MzJcbi8vIC0gZW5jb2RpbmcgLSBhbiBvcHRpb25hbCBlbmNvZGluZywgcmVsZXZhbnQgaXMgdmFsIGlzIGEgc3RyaW5nXG4vLyAtIGRpciAtIHRydWUgZm9yIGluZGV4T2YsIGZhbHNlIGZvciBsYXN0SW5kZXhPZlxuZnVuY3Rpb24gYmlkaXJlY3Rpb25hbEluZGV4T2YgKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKSB7XG4gIC8vIEVtcHR5IGJ1ZmZlciBtZWFucyBubyBtYXRjaFxuICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkgcmV0dXJuIC0xXG5cbiAgLy8gTm9ybWFsaXplIGJ5dGVPZmZzZXRcbiAgaWYgKHR5cGVvZiBieXRlT2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGVuY29kaW5nID0gYnl0ZU9mZnNldFxuICAgIGJ5dGVPZmZzZXQgPSAwXG4gIH0gZWxzZSBpZiAoYnl0ZU9mZnNldCA+IDB4N2ZmZmZmZmYpIHtcbiAgICBieXRlT2Zmc2V0ID0gMHg3ZmZmZmZmZlxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPCAtMHg4MDAwMDAwMCkge1xuICAgIGJ5dGVPZmZzZXQgPSAtMHg4MDAwMDAwMFxuICB9XG4gIGJ5dGVPZmZzZXQgPSArYnl0ZU9mZnNldCAgLy8gQ29lcmNlIHRvIE51bWJlci5cbiAgaWYgKGlzTmFOKGJ5dGVPZmZzZXQpKSB7XG4gICAgLy8gYnl0ZU9mZnNldDogaXQgaXQncyB1bmRlZmluZWQsIG51bGwsIE5hTiwgXCJmb29cIiwgZXRjLCBzZWFyY2ggd2hvbGUgYnVmZmVyXG4gICAgYnl0ZU9mZnNldCA9IGRpciA/IDAgOiAoYnVmZmVyLmxlbmd0aCAtIDEpXG4gIH1cblxuICAvLyBOb3JtYWxpemUgYnl0ZU9mZnNldDogbmVnYXRpdmUgb2Zmc2V0cyBzdGFydCBmcm9tIHRoZSBlbmQgb2YgdGhlIGJ1ZmZlclxuICBpZiAoYnl0ZU9mZnNldCA8IDApIGJ5dGVPZmZzZXQgPSBidWZmZXIubGVuZ3RoICsgYnl0ZU9mZnNldFxuICBpZiAoYnl0ZU9mZnNldCA+PSBidWZmZXIubGVuZ3RoKSB7XG4gICAgaWYgKGRpcikgcmV0dXJuIC0xXG4gICAgZWxzZSBieXRlT2Zmc2V0ID0gYnVmZmVyLmxlbmd0aCAtIDFcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgMCkge1xuICAgIGlmIChkaXIpIGJ5dGVPZmZzZXQgPSAwXG4gICAgZWxzZSByZXR1cm4gLTFcbiAgfVxuXG4gIC8vIE5vcm1hbGl6ZSB2YWxcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnKSB7XG4gICAgdmFsID0gQnVmZmVyLmZyb20odmFsLCBlbmNvZGluZylcbiAgfVxuXG4gIC8vIEZpbmFsbHksIHNlYXJjaCBlaXRoZXIgaW5kZXhPZiAoaWYgZGlyIGlzIHRydWUpIG9yIGxhc3RJbmRleE9mXG4gIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsKSkge1xuICAgIC8vIFNwZWNpYWwgY2FzZTogbG9va2luZyBmb3IgZW1wdHkgc3RyaW5nL2J1ZmZlciBhbHdheXMgZmFpbHNcbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIC0xXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH0gZWxzZSBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICB2YWwgPSB2YWwgJiAweEZGIC8vIFNlYXJjaCBmb3IgYSBieXRlIHZhbHVlIFswLTI1NV1cbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiZcbiAgICAgICAgdHlwZW9mIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGlmIChkaXIpIHtcbiAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5sYXN0SW5kZXhPZi5jYWxsKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0KVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlciwgWyB2YWwgXSwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcilcbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZhbCBtdXN0IGJlIHN0cmluZywgbnVtYmVyIG9yIEJ1ZmZlcicpXG59XG5cbmZ1bmN0aW9uIGFycmF5SW5kZXhPZiAoYXJyLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpIHtcbiAgdmFyIGluZGV4U2l6ZSA9IDFcbiAgdmFyIGFyckxlbmd0aCA9IGFyci5sZW5ndGhcbiAgdmFyIHZhbExlbmd0aCA9IHZhbC5sZW5ndGhcblxuICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgaWYgKGVuY29kaW5nID09PSAndWNzMicgfHwgZW5jb2RpbmcgPT09ICd1Y3MtMicgfHxcbiAgICAgICAgZW5jb2RpbmcgPT09ICd1dGYxNmxlJyB8fCBlbmNvZGluZyA9PT0gJ3V0Zi0xNmxlJykge1xuICAgICAgaWYgKGFyci5sZW5ndGggPCAyIHx8IHZhbC5sZW5ndGggPCAyKSB7XG4gICAgICAgIHJldHVybiAtMVxuICAgICAgfVxuICAgICAgaW5kZXhTaXplID0gMlxuICAgICAgYXJyTGVuZ3RoIC89IDJcbiAgICAgIHZhbExlbmd0aCAvPSAyXG4gICAgICBieXRlT2Zmc2V0IC89IDJcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiByZWFkIChidWYsIGkpIHtcbiAgICBpZiAoaW5kZXhTaXplID09PSAxKSB7XG4gICAgICByZXR1cm4gYnVmW2ldXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBidWYucmVhZFVJbnQxNkJFKGkgKiBpbmRleFNpemUpXG4gICAgfVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGRpcikge1xuICAgIHZhciBmb3VuZEluZGV4ID0gLTFcbiAgICBmb3IgKGkgPSBieXRlT2Zmc2V0OyBpIDwgYXJyTGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChyZWFkKGFyciwgaSkgPT09IHJlYWQodmFsLCBmb3VuZEluZGV4ID09PSAtMSA/IDAgOiBpIC0gZm91bmRJbmRleCkpIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggPT09IC0xKSBmb3VuZEluZGV4ID0gaVxuICAgICAgICBpZiAoaSAtIGZvdW5kSW5kZXggKyAxID09PSB2YWxMZW5ndGgpIHJldHVybiBmb3VuZEluZGV4ICogaW5kZXhTaXplXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZm91bmRJbmRleCAhPT0gLTEpIGkgLT0gaSAtIGZvdW5kSW5kZXhcbiAgICAgICAgZm91bmRJbmRleCA9IC0xXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChieXRlT2Zmc2V0ICsgdmFsTGVuZ3RoID4gYXJyTGVuZ3RoKSBieXRlT2Zmc2V0ID0gYXJyTGVuZ3RoIC0gdmFsTGVuZ3RoXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHZhciBmb3VuZCA9IHRydWVcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdmFsTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKHJlYWQoYXJyLCBpICsgaikgIT09IHJlYWQodmFsLCBqKSkge1xuICAgICAgICAgIGZvdW5kID0gZmFsc2VcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoZm91bmQpIHJldHVybiBpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIC0xXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5jbHVkZXMgPSBmdW5jdGlvbiBpbmNsdWRlcyAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gdGhpcy5pbmRleE9mKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpICE9PSAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiBpbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCB0cnVlKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmxhc3RJbmRleE9mID0gZnVuY3Rpb24gbGFzdEluZGV4T2YgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIGJpZGlyZWN0aW9uYWxJbmRleE9mKHRoaXMsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGZhbHNlKVxufVxuXG5mdW5jdGlvbiBoZXhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIC8vIG11c3QgYmUgYW4gZXZlbiBudW1iZXIgb2YgZGlnaXRzXG4gIHZhciBzdHJMZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChzdHJMZW4gJSAyICE9PSAwKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICB2YXIgcGFyc2VkID0gcGFyc2VJbnQoc3RyaW5nLnN1YnN0cihpICogMiwgMiksIDE2KVxuICAgIGlmIChpc05hTihwYXJzZWQpKSByZXR1cm4gaVxuICAgIGJ1ZltvZmZzZXQgKyBpXSA9IHBhcnNlZFxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGFzY2lpV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gbGF0aW4xV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB1Y3MyV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gd3JpdGUgKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgb2Zmc2V0WywgbGVuZ3RoXVssIGVuY29kaW5nXSlcbiAgfSBlbHNlIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICAgIGlmIChpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBsZW5ndGggPSBsZW5ndGggfCAwXG4gICAgICBpZiAoZW5jb2RpbmcgPT09IHVuZGVmaW5lZCkgZW5jb2RpbmcgPSAndXRmOCdcbiAgICB9IGVsc2Uge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgLy8gbGVnYWN5IHdyaXRlKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldCwgbGVuZ3RoKSAtIHJlbW92ZSBpbiB2MC4xM1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICdCdWZmZXIud3JpdGUoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0WywgbGVuZ3RoXSkgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZCdcbiAgICApXG4gIH1cblxuICB2YXIgcmVtYWluaW5nID0gdGhpcy5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkIHx8IGxlbmd0aCA+IHJlbWFpbmluZykgbGVuZ3RoID0gcmVtYWluaW5nXG5cbiAgaWYgKChzdHJpbmcubGVuZ3RoID4gMCAmJiAobGVuZ3RoIDwgMCB8fCBvZmZzZXQgPCAwKSkgfHwgb2Zmc2V0ID4gdGhpcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQXR0ZW1wdCB0byB3cml0ZSBvdXRzaWRlIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcblxuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBsYXRpbjFXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICAvLyBXYXJuaW5nOiBtYXhMZW5ndGggbm90IHRha2VuIGludG8gYWNjb3VudCBpbiBiYXNlNjRXcml0ZVxuICAgICAgICByZXR1cm4gYmFzZTY0V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIHVjczJXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoJycgKyBlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04gKCkge1xuICByZXR1cm4ge1xuICAgIHR5cGU6ICdCdWZmZXInLFxuICAgIGRhdGE6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuX2FyciB8fCB0aGlzLCAwKVxuICB9XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKHN0YXJ0ID09PSAwICYmIGVuZCA9PT0gYnVmLmxlbmd0aCkge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1Zi5zbGljZShzdGFydCwgZW5kKSlcbiAgfVxufVxuXG5mdW5jdGlvbiB1dGY4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG4gIHZhciByZXMgPSBbXVxuXG4gIHZhciBpID0gc3RhcnRcbiAgd2hpbGUgKGkgPCBlbmQpIHtcbiAgICB2YXIgZmlyc3RCeXRlID0gYnVmW2ldXG4gICAgdmFyIGNvZGVQb2ludCA9IG51bGxcbiAgICB2YXIgYnl0ZXNQZXJTZXF1ZW5jZSA9IChmaXJzdEJ5dGUgPiAweEVGKSA/IDRcbiAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4REYpID8gM1xuICAgICAgOiAoZmlyc3RCeXRlID4gMHhCRikgPyAyXG4gICAgICA6IDFcblxuICAgIGlmIChpICsgYnl0ZXNQZXJTZXF1ZW5jZSA8PSBlbmQpIHtcbiAgICAgIHZhciBzZWNvbmRCeXRlLCB0aGlyZEJ5dGUsIGZvdXJ0aEJ5dGUsIHRlbXBDb2RlUG9pbnRcblxuICAgICAgc3dpdGNoIChieXRlc1BlclNlcXVlbmNlKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICBpZiAoZmlyc3RCeXRlIDwgMHg4MCkge1xuICAgICAgICAgICAgY29kZVBvaW50ID0gZmlyc3RCeXRlXG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4MUYpIDw8IDB4NiB8IChzZWNvbmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3Rikge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweEMgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4NiB8ICh0aGlyZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGRiAmJiAodGVtcENvZGVQb2ludCA8IDB4RDgwMCB8fCB0ZW1wQ29kZVBvaW50ID4gMHhERkZGKSkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICBzZWNvbmRCeXRlID0gYnVmW2kgKyAxXVxuICAgICAgICAgIHRoaXJkQnl0ZSA9IGJ1ZltpICsgMl1cbiAgICAgICAgICBmb3VydGhCeXRlID0gYnVmW2kgKyAzXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAoZm91cnRoQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHgxMiB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHhDIHwgKHRoaXJkQnl0ZSAmIDB4M0YpIDw8IDB4NiB8IChmb3VydGhCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHhGRkZGICYmIHRlbXBDb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgICAgICAgICBjb2RlUG9pbnQgPSB0ZW1wQ29kZVBvaW50XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb2RlUG9pbnQgPT09IG51bGwpIHtcbiAgICAgIC8vIHdlIGRpZCBub3QgZ2VuZXJhdGUgYSB2YWxpZCBjb2RlUG9pbnQgc28gaW5zZXJ0IGFcbiAgICAgIC8vIHJlcGxhY2VtZW50IGNoYXIgKFUrRkZGRCkgYW5kIGFkdmFuY2Ugb25seSAxIGJ5dGVcbiAgICAgIGNvZGVQb2ludCA9IDB4RkZGRFxuICAgICAgYnl0ZXNQZXJTZXF1ZW5jZSA9IDFcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA+IDB4RkZGRikge1xuICAgICAgLy8gZW5jb2RlIHRvIHV0ZjE2IChzdXJyb2dhdGUgcGFpciBkYW5jZSlcbiAgICAgIGNvZGVQb2ludCAtPSAweDEwMDAwXG4gICAgICByZXMucHVzaChjb2RlUG9pbnQgPj4+IDEwICYgMHgzRkYgfCAweEQ4MDApXG4gICAgICBjb2RlUG9pbnQgPSAweERDMDAgfCBjb2RlUG9pbnQgJiAweDNGRlxuICAgIH1cblxuICAgIHJlcy5wdXNoKGNvZGVQb2ludClcbiAgICBpICs9IGJ5dGVzUGVyU2VxdWVuY2VcbiAgfVxuXG4gIHJldHVybiBkZWNvZGVDb2RlUG9pbnRzQXJyYXkocmVzKVxufVxuXG4vLyBCYXNlZCBvbiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMjc0NzI3Mi82ODA3NDIsIHRoZSBicm93c2VyIHdpdGhcbi8vIHRoZSBsb3dlc3QgbGltaXQgaXMgQ2hyb21lLCB3aXRoIDB4MTAwMDAgYXJncy5cbi8vIFdlIGdvIDEgbWFnbml0dWRlIGxlc3MsIGZvciBzYWZldHlcbnZhciBNQVhfQVJHVU1FTlRTX0xFTkdUSCA9IDB4MTAwMFxuXG5mdW5jdGlvbiBkZWNvZGVDb2RlUG9pbnRzQXJyYXkgKGNvZGVQb2ludHMpIHtcbiAgdmFyIGxlbiA9IGNvZGVQb2ludHMubGVuZ3RoXG4gIGlmIChsZW4gPD0gTUFYX0FSR1VNRU5UU19MRU5HVEgpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNvZGVQb2ludHMpIC8vIGF2b2lkIGV4dHJhIHNsaWNlKClcbiAgfVxuXG4gIC8vIERlY29kZSBpbiBjaHVua3MgdG8gYXZvaWQgXCJjYWxsIHN0YWNrIHNpemUgZXhjZWVkZWRcIi5cbiAgdmFyIHJlcyA9ICcnXG4gIHZhciBpID0gMFxuICB3aGlsZSAoaSA8IGxlbikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFxuICAgICAgU3RyaW5nLFxuICAgICAgY29kZVBvaW50cy5zbGljZShpLCBpICs9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKVxuICAgIClcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldICYgMHg3RilcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbmZ1bmN0aW9uIGxhdGluMVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbmZ1bmN0aW9uIGhleFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcblxuICBpZiAoIXN0YXJ0IHx8IHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmICghZW5kIHx8IGVuZCA8IDAgfHwgZW5kID4gbGVuKSBlbmQgPSBsZW5cblxuICB2YXIgb3V0ID0gJydcbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICBvdXQgKz0gdG9IZXgoYnVmW2ldKVxuICB9XG4gIHJldHVybiBvdXRcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGJ5dGVzID0gYnVmLnNsaWNlKHN0YXJ0LCBlbmQpXG4gIHZhciByZXMgPSAnJ1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0gKyBieXRlc1tpICsgMV0gKiAyNTYpXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24gc2xpY2UgKHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIHN0YXJ0ID0gfn5zdGFydFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCA/IGxlbiA6IH5+ZW5kXG5cbiAgaWYgKHN0YXJ0IDwgMCkge1xuICAgIHN0YXJ0ICs9IGxlblxuICAgIGlmIChzdGFydCA8IDApIHN0YXJ0ID0gMFxuICB9IGVsc2UgaWYgKHN0YXJ0ID4gbGVuKSB7XG4gICAgc3RhcnQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCAwKSB7XG4gICAgZW5kICs9IGxlblxuICAgIGlmIChlbmQgPCAwKSBlbmQgPSAwXG4gIH0gZWxzZSBpZiAoZW5kID4gbGVuKSB7XG4gICAgZW5kID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgc3RhcnQpIGVuZCA9IHN0YXJ0XG5cbiAgdmFyIG5ld0J1ZlxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICBuZXdCdWYgPSB0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpXG4gICAgbmV3QnVmLl9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgfSBlbHNlIHtcbiAgICB2YXIgc2xpY2VMZW4gPSBlbmQgLSBzdGFydFxuICAgIG5ld0J1ZiA9IG5ldyBCdWZmZXIoc2xpY2VMZW4sIHVuZGVmaW5lZClcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNsaWNlTGVuOyArK2kpIHtcbiAgICAgIG5ld0J1ZltpXSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdCdWZcbn1cblxuLypcbiAqIE5lZWQgdG8gbWFrZSBzdXJlIHRoYXQgYnVmZmVyIGlzbid0IHRyeWluZyB0byB3cml0ZSBvdXQgb2YgYm91bmRzLlxuICovXG5mdW5jdGlvbiBjaGVja09mZnNldCAob2Zmc2V0LCBleHQsIGxlbmd0aCkge1xuICBpZiAoKG9mZnNldCAlIDEpICE9PSAwIHx8IG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdvZmZzZXQgaXMgbm90IHVpbnQnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gbGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRMRSA9IGZ1bmN0aW9uIHJlYWRVSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRCRSA9IGZ1bmN0aW9uIHJlYWRVSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG4gIH1cblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdXG4gIHZhciBtdWwgPSAxXG4gIHdoaWxlIChieXRlTGVuZ3RoID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF0gKiBtdWxcbiAgfVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDggPSBmdW5jdGlvbiByZWFkVUludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2QkUgPSBmdW5jdGlvbiByZWFkVUludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgOCkgfCB0aGlzW29mZnNldCArIDFdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkxFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICgodGhpc1tvZmZzZXRdKSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikpICtcbiAgICAgICh0aGlzW29mZnNldCArIDNdICogMHgxMDAwMDAwKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdICogMHgxMDAwMDAwKSArXG4gICAgKCh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgIHRoaXNbb2Zmc2V0ICsgM10pXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludExFID0gZnVuY3Rpb24gcmVhZEludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG4gIG11bCAqPSAweDgwXG5cbiAgaWYgKHZhbCA+PSBtdWwpIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludEJFID0gZnVuY3Rpb24gcmVhZEludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIGkgPSBieXRlTGVuZ3RoXG4gIHZhciBtdWwgPSAxXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0taV1cbiAgd2hpbGUgKGkgPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1pXSAqIG11bFxuICB9XG4gIG11bCAqPSAweDgwXG5cbiAgaWYgKHZhbCA+PSBtdWwpIHZhbCAtPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aClcblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbiByZWFkSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICBpZiAoISh0aGlzW29mZnNldF0gJiAweDgwKSkgcmV0dXJuICh0aGlzW29mZnNldF0pXG4gIHJldHVybiAoKDB4ZmYgLSB0aGlzW29mZnNldF0gKyAxKSAqIC0xKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24gcmVhZEludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIDFdIHwgKHRoaXNbb2Zmc2V0XSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiByZWFkSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdKSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgM10gPDwgMjQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyQkUgPSBmdW5jdGlvbiByZWFkSW50MzJCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDI0KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgM10pXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0TEUgPSBmdW5jdGlvbiByZWFkRmxvYXRMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiByZWFkRmxvYXRCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgdHJ1ZSwgNTIsIDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUJFID0gZnVuY3Rpb24gcmVhZERvdWJsZUJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgNTIsIDgpXG59XG5cbmZ1bmN0aW9uIGNoZWNrSW50IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJidWZmZXJcIiBhcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyIGluc3RhbmNlJylcbiAgaWYgKHZhbHVlID4gbWF4IHx8IHZhbHVlIDwgbWluKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJ2YWx1ZVwiIGFyZ3VtZW50IGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBtYXhCeXRlcyA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSAtIDFcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBtYXhCeXRlcywgMClcbiAgfVxuXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIHZhciBtYXhCeXRlcyA9IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKSAtIDFcbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBtYXhCeXRlcywgMClcbiAgfVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50OCA9IGZ1bmN0aW9uIHdyaXRlVUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHhmZiwgMClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkgdmFsdWUgPSBNYXRoLmZsb29yKHZhbHVlKVxuICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmYgKyB2YWx1ZSArIDFcbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihidWYubGVuZ3RoIC0gb2Zmc2V0LCAyKTsgaSA8IGo7ICsraSkge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9ICh2YWx1ZSAmICgweGZmIDw8ICg4ICogKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkpKSkgPj4+XG4gICAgICAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSAqIDhcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQzMiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgNCk7IGkgPCBqOyArK2kpIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgPj4+IChsaXR0bGVFbmRpYW4gPyBpIDogMyAtIGkpICogOCkgJiAweGZmXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50TEUgPSBmdW5jdGlvbiB3cml0ZUludExFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gMFxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICBpZiAodmFsdWUgPCAwICYmIHN1YiA9PT0gMCAmJiB0aGlzW29mZnNldCArIGkgLSAxXSAhPT0gMCkge1xuICAgICAgc3ViID0gMVxuICAgIH1cbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50QkUgPSBmdW5jdGlvbiB3cml0ZUludEJFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHN1YiA9IDBcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICBpZiAodmFsdWUgPCAwICYmIHN1YiA9PT0gMCAmJiB0aGlzW29mZnNldCArIGkgKyAxXSAhPT0gMCkge1xuICAgICAgc3ViID0gMVxuICAgIH1cbiAgICB0aGlzW29mZnNldCArIGldID0gKCh2YWx1ZSAvIG11bCkgPj4gMCkgLSBzdWIgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50OCA9IGZ1bmN0aW9uIHdyaXRlSW50OCAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAxLCAweDdmLCAtMHg4MClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkgdmFsdWUgPSBNYXRoLmZsb29yKHZhbHVlKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmYgKyB2YWx1ZSArIDFcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2TEUgPSBmdW5jdGlvbiB3cml0ZUludDE2TEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlICYgMHhmZilcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgPj4+IDI0KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZUludDMyQkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmZmZmZiArIHZhbHVlICsgMVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuZnVuY3Rpb24gY2hlY2tJRUVFNzU0IChidWYsIHZhbHVlLCBvZmZzZXQsIGV4dCwgbWF4LCBtaW4pIHtcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAob2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgNCwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gd3JpdGVGbG9hdExFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5ICh0YXJnZXQsIHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXRTdGFydCA+PSB0YXJnZXQubGVuZ3RoKSB0YXJnZXRTdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRTdGFydCkgdGFyZ2V0U3RhcnQgPSAwXG4gIGlmIChlbmQgPiAwICYmIGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuIDBcbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgdGhpcy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBpZiAodGFyZ2V0U3RhcnQgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICB9XG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0IDwgZW5kIC0gc3RhcnQpIHtcbiAgICBlbmQgPSB0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgKyBzdGFydFxuICB9XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG4gIHZhciBpXG5cbiAgaWYgKHRoaXMgPT09IHRhcmdldCAmJiBzdGFydCA8IHRhcmdldFN0YXJ0ICYmIHRhcmdldFN0YXJ0IDwgZW5kKSB7XG4gICAgLy8gZGVzY2VuZGluZyBjb3B5IGZyb20gZW5kXG4gICAgZm9yIChpID0gbGVuIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2UgaWYgKGxlbiA8IDEwMDAgfHwgIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gYXNjZW5kaW5nIGNvcHkgZnJvbSBzdGFydFxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47ICsraSkge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgVWludDhBcnJheS5wcm90b3R5cGUuc2V0LmNhbGwoXG4gICAgICB0YXJnZXQsXG4gICAgICB0aGlzLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGxlbiksXG4gICAgICB0YXJnZXRTdGFydFxuICAgIClcbiAgfVxuXG4gIHJldHVybiBsZW5cbn1cblxuLy8gVXNhZ2U6XG4vLyAgICBidWZmZXIuZmlsbChudW1iZXJbLCBvZmZzZXRbLCBlbmRdXSlcbi8vICAgIGJ1ZmZlci5maWxsKGJ1ZmZlclssIG9mZnNldFssIGVuZF1dKVxuLy8gICAgYnVmZmVyLmZpbGwoc3RyaW5nWywgb2Zmc2V0WywgZW5kXV1bLCBlbmNvZGluZ10pXG5CdWZmZXIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbiBmaWxsICh2YWwsIHN0YXJ0LCBlbmQsIGVuY29kaW5nKSB7XG4gIC8vIEhhbmRsZSBzdHJpbmcgY2FzZXM6XG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgIGlmICh0eXBlb2Ygc3RhcnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBlbmNvZGluZyA9IHN0YXJ0XG4gICAgICBzdGFydCA9IDBcbiAgICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZW5kID09PSAnc3RyaW5nJykge1xuICAgICAgZW5jb2RpbmcgPSBlbmRcbiAgICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gICAgfVxuICAgIGlmICh2YWwubGVuZ3RoID09PSAxKSB7XG4gICAgICB2YXIgY29kZSA9IHZhbC5jaGFyQ29kZUF0KDApXG4gICAgICBpZiAoY29kZSA8IDI1Nikge1xuICAgICAgICB2YWwgPSBjb2RlXG4gICAgICB9XG4gICAgfVxuICAgIGlmIChlbmNvZGluZyAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuY29kaW5nIG11c3QgYmUgYSBzdHJpbmcnKVxuICAgIH1cbiAgICBpZiAodHlwZW9mIGVuY29kaW5nID09PSAnc3RyaW5nJyAmJiAhQnVmZmVyLmlzRW5jb2RpbmcoZW5jb2RpbmcpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgdmFsID0gdmFsICYgMjU1XG4gIH1cblxuICAvLyBJbnZhbGlkIHJhbmdlcyBhcmUgbm90IHNldCB0byBhIGRlZmF1bHQsIHNvIGNhbiByYW5nZSBjaGVjayBlYXJseS5cbiAgaWYgKHN0YXJ0IDwgMCB8fCB0aGlzLmxlbmd0aCA8IHN0YXJ0IHx8IHRoaXMubGVuZ3RoIDwgZW5kKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ091dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHN0YXJ0ID0gc3RhcnQgPj4+IDBcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyB0aGlzLmxlbmd0aCA6IGVuZCA+Pj4gMFxuXG4gIGlmICghdmFsKSB2YWwgPSAwXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgICAgdGhpc1tpXSA9IHZhbFxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgYnl0ZXMgPSBCdWZmZXIuaXNCdWZmZXIodmFsKVxuICAgICAgPyB2YWxcbiAgICAgIDogdXRmOFRvQnl0ZXMobmV3IEJ1ZmZlcih2YWwsIGVuY29kaW5nKS50b1N0cmluZygpKVxuICAgIHZhciBsZW4gPSBieXRlcy5sZW5ndGhcbiAgICBmb3IgKGkgPSAwOyBpIDwgZW5kIC0gc3RhcnQ7ICsraSkge1xuICAgICAgdGhpc1tpICsgc3RhcnRdID0gYnl0ZXNbaSAlIGxlbl1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpc1xufVxuXG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09XG5cbnZhciBJTlZBTElEX0JBU0U2NF9SRSA9IC9bXitcXC8wLTlBLVphLXotX10vZ1xuXG5mdW5jdGlvbiBiYXNlNjRjbGVhbiAoc3RyKSB7XG4gIC8vIE5vZGUgc3RyaXBzIG91dCBpbnZhbGlkIGNoYXJhY3RlcnMgbGlrZSBcXG4gYW5kIFxcdCBmcm9tIHRoZSBzdHJpbmcsIGJhc2U2NC1qcyBkb2VzIG5vdFxuICBzdHIgPSBzdHJpbmd0cmltKHN0cikucmVwbGFjZShJTlZBTElEX0JBU0U2NF9SRSwgJycpXG4gIC8vIE5vZGUgY29udmVydHMgc3RyaW5ncyB3aXRoIGxlbmd0aCA8IDIgdG8gJydcbiAgaWYgKHN0ci5sZW5ndGggPCAyKSByZXR1cm4gJydcbiAgLy8gTm9kZSBhbGxvd3MgZm9yIG5vbi1wYWRkZWQgYmFzZTY0IHN0cmluZ3MgKG1pc3NpbmcgdHJhaWxpbmcgPT09KSwgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHdoaWxlIChzdHIubGVuZ3RoICUgNCAhPT0gMCkge1xuICAgIHN0ciA9IHN0ciArICc9J1xuICB9XG4gIHJldHVybiBzdHJcbn1cblxuZnVuY3Rpb24gc3RyaW5ndHJpbSAoc3RyKSB7XG4gIGlmIChzdHIudHJpbSkgcmV0dXJuIHN0ci50cmltKClcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJylcbn1cblxuZnVuY3Rpb24gdG9IZXggKG4pIHtcbiAgaWYgKG4gPCAxNikgcmV0dXJuICcwJyArIG4udG9TdHJpbmcoMTYpXG4gIHJldHVybiBuLnRvU3RyaW5nKDE2KVxufVxuXG5mdW5jdGlvbiB1dGY4VG9CeXRlcyAoc3RyaW5nLCB1bml0cykge1xuICB1bml0cyA9IHVuaXRzIHx8IEluZmluaXR5XG4gIHZhciBjb2RlUG9pbnRcbiAgdmFyIGxlbmd0aCA9IHN0cmluZy5sZW5ndGhcbiAgdmFyIGxlYWRTdXJyb2dhdGUgPSBudWxsXG4gIHZhciBieXRlcyA9IFtdXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGNvZGVQb2ludCA9IHN0cmluZy5jaGFyQ29kZUF0KGkpXG5cbiAgICAvLyBpcyBzdXJyb2dhdGUgY29tcG9uZW50XG4gICAgaWYgKGNvZGVQb2ludCA+IDB4RDdGRiAmJiBjb2RlUG9pbnQgPCAweEUwMDApIHtcbiAgICAgIC8vIGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoIWxlYWRTdXJyb2dhdGUpIHtcbiAgICAgICAgLy8gbm8gbGVhZCB5ZXRcbiAgICAgICAgaWYgKGNvZGVQb2ludCA+IDB4REJGRikge1xuICAgICAgICAgIC8vIHVuZXhwZWN0ZWQgdHJhaWxcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9IGVsc2UgaWYgKGkgKyAxID09PSBsZW5ndGgpIHtcbiAgICAgICAgICAvLyB1bnBhaXJlZCBsZWFkXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHZhbGlkIGxlYWRcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIDIgbGVhZHMgaW4gYSByb3dcbiAgICAgIGlmIChjb2RlUG9pbnQgPCAweERDMDApIHtcbiAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gdmFsaWQgc3Vycm9nYXRlIHBhaXJcbiAgICAgIGNvZGVQb2ludCA9IChsZWFkU3Vycm9nYXRlIC0gMHhEODAwIDw8IDEwIHwgY29kZVBvaW50IC0gMHhEQzAwKSArIDB4MTAwMDBcbiAgICB9IGVsc2UgaWYgKGxlYWRTdXJyb2dhdGUpIHtcbiAgICAgIC8vIHZhbGlkIGJtcCBjaGFyLCBidXQgbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgIH1cblxuICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG5cbiAgICAvLyBlbmNvZGUgdXRmOFxuICAgIGlmIChjb2RlUG9pbnQgPCAweDgwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDEpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goY29kZVBvaW50KVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiB8IDB4QzAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgfCAweEUwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSA0KSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHgxMiB8IDB4RjAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29kZSBwb2ludCcpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIC8vIE5vZGUncyBjb2RlIHNlZW1zIHRvIGJlIGRvaW5nIHRoaXMgYW5kIG5vdCAmIDB4N0YuLlxuICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpICYgMHhGRilcbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVUb0J5dGVzIChzdHIsIHVuaXRzKSB7XG4gIHZhciBjLCBoaSwgbG9cbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG5cbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBoaSA9IGMgPj4gOFxuICAgIGxvID0gYyAlIDI1NlxuICAgIGJ5dGVBcnJheS5wdXNoKGxvKVxuICAgIGJ5dGVBcnJheS5wdXNoKGhpKVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBiYXNlNjRUb0J5dGVzIChzdHIpIHtcbiAgcmV0dXJuIGJhc2U2NC50b0J5dGVBcnJheShiYXNlNjRjbGVhbihzdHIpKVxufVxuXG5mdW5jdGlvbiBibGl0QnVmZmVyIChzcmMsIGRzdCwgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkge1xuICAgIGlmICgoaSArIG9mZnNldCA+PSBkc3QubGVuZ3RoKSB8fCAoaSA+PSBzcmMubGVuZ3RoKSkgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuXG5mdW5jdGlvbiBpc25hbiAodmFsKSB7XG4gIHJldHVybiB2YWwgIT09IHZhbCAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXNlbGYtY29tcGFyZVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIFwiMTAwXCI6IFwiQ29udGludWVcIixcbiAgXCIxMDFcIjogXCJTd2l0Y2hpbmcgUHJvdG9jb2xzXCIsXG4gIFwiMTAyXCI6IFwiUHJvY2Vzc2luZ1wiLFxuICBcIjIwMFwiOiBcIk9LXCIsXG4gIFwiMjAxXCI6IFwiQ3JlYXRlZFwiLFxuICBcIjIwMlwiOiBcIkFjY2VwdGVkXCIsXG4gIFwiMjAzXCI6IFwiTm9uLUF1dGhvcml0YXRpdmUgSW5mb3JtYXRpb25cIixcbiAgXCIyMDRcIjogXCJObyBDb250ZW50XCIsXG4gIFwiMjA1XCI6IFwiUmVzZXQgQ29udGVudFwiLFxuICBcIjIwNlwiOiBcIlBhcnRpYWwgQ29udGVudFwiLFxuICBcIjIwN1wiOiBcIk11bHRpLVN0YXR1c1wiLFxuICBcIjIwOFwiOiBcIkFscmVhZHkgUmVwb3J0ZWRcIixcbiAgXCIyMjZcIjogXCJJTSBVc2VkXCIsXG4gIFwiMzAwXCI6IFwiTXVsdGlwbGUgQ2hvaWNlc1wiLFxuICBcIjMwMVwiOiBcIk1vdmVkIFBlcm1hbmVudGx5XCIsXG4gIFwiMzAyXCI6IFwiRm91bmRcIixcbiAgXCIzMDNcIjogXCJTZWUgT3RoZXJcIixcbiAgXCIzMDRcIjogXCJOb3QgTW9kaWZpZWRcIixcbiAgXCIzMDVcIjogXCJVc2UgUHJveHlcIixcbiAgXCIzMDdcIjogXCJUZW1wb3JhcnkgUmVkaXJlY3RcIixcbiAgXCIzMDhcIjogXCJQZXJtYW5lbnQgUmVkaXJlY3RcIixcbiAgXCI0MDBcIjogXCJCYWQgUmVxdWVzdFwiLFxuICBcIjQwMVwiOiBcIlVuYXV0aG9yaXplZFwiLFxuICBcIjQwMlwiOiBcIlBheW1lbnQgUmVxdWlyZWRcIixcbiAgXCI0MDNcIjogXCJGb3JiaWRkZW5cIixcbiAgXCI0MDRcIjogXCJOb3QgRm91bmRcIixcbiAgXCI0MDVcIjogXCJNZXRob2QgTm90IEFsbG93ZWRcIixcbiAgXCI0MDZcIjogXCJOb3QgQWNjZXB0YWJsZVwiLFxuICBcIjQwN1wiOiBcIlByb3h5IEF1dGhlbnRpY2F0aW9uIFJlcXVpcmVkXCIsXG4gIFwiNDA4XCI6IFwiUmVxdWVzdCBUaW1lb3V0XCIsXG4gIFwiNDA5XCI6IFwiQ29uZmxpY3RcIixcbiAgXCI0MTBcIjogXCJHb25lXCIsXG4gIFwiNDExXCI6IFwiTGVuZ3RoIFJlcXVpcmVkXCIsXG4gIFwiNDEyXCI6IFwiUHJlY29uZGl0aW9uIEZhaWxlZFwiLFxuICBcIjQxM1wiOiBcIlBheWxvYWQgVG9vIExhcmdlXCIsXG4gIFwiNDE0XCI6IFwiVVJJIFRvbyBMb25nXCIsXG4gIFwiNDE1XCI6IFwiVW5zdXBwb3J0ZWQgTWVkaWEgVHlwZVwiLFxuICBcIjQxNlwiOiBcIlJhbmdlIE5vdCBTYXRpc2ZpYWJsZVwiLFxuICBcIjQxN1wiOiBcIkV4cGVjdGF0aW9uIEZhaWxlZFwiLFxuICBcIjQxOFwiOiBcIkknbSBhIHRlYXBvdFwiLFxuICBcIjQyMVwiOiBcIk1pc2RpcmVjdGVkIFJlcXVlc3RcIixcbiAgXCI0MjJcIjogXCJVbnByb2Nlc3NhYmxlIEVudGl0eVwiLFxuICBcIjQyM1wiOiBcIkxvY2tlZFwiLFxuICBcIjQyNFwiOiBcIkZhaWxlZCBEZXBlbmRlbmN5XCIsXG4gIFwiNDI1XCI6IFwiVW5vcmRlcmVkIENvbGxlY3Rpb25cIixcbiAgXCI0MjZcIjogXCJVcGdyYWRlIFJlcXVpcmVkXCIsXG4gIFwiNDI4XCI6IFwiUHJlY29uZGl0aW9uIFJlcXVpcmVkXCIsXG4gIFwiNDI5XCI6IFwiVG9vIE1hbnkgUmVxdWVzdHNcIixcbiAgXCI0MzFcIjogXCJSZXF1ZXN0IEhlYWRlciBGaWVsZHMgVG9vIExhcmdlXCIsXG4gIFwiNDUxXCI6IFwiVW5hdmFpbGFibGUgRm9yIExlZ2FsIFJlYXNvbnNcIixcbiAgXCI1MDBcIjogXCJJbnRlcm5hbCBTZXJ2ZXIgRXJyb3JcIixcbiAgXCI1MDFcIjogXCJOb3QgSW1wbGVtZW50ZWRcIixcbiAgXCI1MDJcIjogXCJCYWQgR2F0ZXdheVwiLFxuICBcIjUwM1wiOiBcIlNlcnZpY2UgVW5hdmFpbGFibGVcIixcbiAgXCI1MDRcIjogXCJHYXRld2F5IFRpbWVvdXRcIixcbiAgXCI1MDVcIjogXCJIVFRQIFZlcnNpb24gTm90IFN1cHBvcnRlZFwiLFxuICBcIjUwNlwiOiBcIlZhcmlhbnQgQWxzbyBOZWdvdGlhdGVzXCIsXG4gIFwiNTA3XCI6IFwiSW5zdWZmaWNpZW50IFN0b3JhZ2VcIixcbiAgXCI1MDhcIjogXCJMb29wIERldGVjdGVkXCIsXG4gIFwiNTA5XCI6IFwiQmFuZHdpZHRoIExpbWl0IEV4Y2VlZGVkXCIsXG4gIFwiNTEwXCI6IFwiTm90IEV4dGVuZGVkXCIsXG4gIFwiNTExXCI6IFwiTmV0d29yayBBdXRoZW50aWNhdGlvbiBSZXF1aXJlZFwiXG59XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuLy8gTk9URTogVGhlc2UgdHlwZSBjaGVja2luZyBmdW5jdGlvbnMgaW50ZW50aW9uYWxseSBkb24ndCB1c2UgYGluc3RhbmNlb2ZgXG4vLyBiZWNhdXNlIGl0IGlzIGZyYWdpbGUgYW5kIGNhbiBiZSBlYXNpbHkgZmFrZWQgd2l0aCBgT2JqZWN0LmNyZWF0ZSgpYC5cblxuZnVuY3Rpb24gaXNBcnJheShhcmcpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkpIHtcbiAgICByZXR1cm4gQXJyYXkuaXNBcnJheShhcmcpO1xuICB9XG4gIHJldHVybiBvYmplY3RUb1N0cmluZyhhcmcpID09PSAnW29iamVjdCBBcnJheV0nO1xufVxuZXhwb3J0cy5pc0FycmF5ID0gaXNBcnJheTtcblxuZnVuY3Rpb24gaXNCb29sZWFuKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nO1xufVxuZXhwb3J0cy5pc0Jvb2xlYW4gPSBpc0Jvb2xlYW47XG5cbmZ1bmN0aW9uIGlzTnVsbChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNOdWxsID0gaXNOdWxsO1xuXG5mdW5jdGlvbiBpc051bGxPclVuZGVmaW5lZChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGxPclVuZGVmaW5lZCA9IGlzTnVsbE9yVW5kZWZpbmVkO1xuXG5mdW5jdGlvbiBpc051bWJlcihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInO1xufVxuZXhwb3J0cy5pc051bWJlciA9IGlzTnVtYmVyO1xuXG5mdW5jdGlvbiBpc1N0cmluZyhhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnO1xufVxuZXhwb3J0cy5pc1N0cmluZyA9IGlzU3RyaW5nO1xuXG5mdW5jdGlvbiBpc1N5bWJvbChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnO1xufVxuZXhwb3J0cy5pc1N5bWJvbCA9IGlzU3ltYm9sO1xuXG5mdW5jdGlvbiBpc1VuZGVmaW5lZChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gdm9pZCAwO1xufVxuZXhwb3J0cy5pc1VuZGVmaW5lZCA9IGlzVW5kZWZpbmVkO1xuXG5mdW5jdGlvbiBpc1JlZ0V4cChyZSkge1xuICByZXR1cm4gb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gKG9iamVjdFRvU3RyaW5nKGUpID09PSAnW29iamVjdCBFcnJvcl0nIHx8IGUgaW5zdGFuY2VvZiBFcnJvcik7XG59XG5leHBvcnRzLmlzRXJyb3IgPSBpc0Vycm9yO1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJztcbn1cbmV4cG9ydHMuaXNGdW5jdGlvbiA9IGlzRnVuY3Rpb247XG5cbmZ1bmN0aW9uIGlzUHJpbWl0aXZlKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnYm9vbGVhbicgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdudW1iZXInIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnc3RyaW5nJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcgfHwgIC8vIEVTNiBzeW1ib2xcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICd1bmRlZmluZWQnO1xufVxuZXhwb3J0cy5pc1ByaW1pdGl2ZSA9IGlzUHJpbWl0aXZlO1xuXG5leHBvcnRzLmlzQnVmZmVyID0gQnVmZmVyLmlzQnVmZmVyO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWFycmF5LyBWZXJzaW9uIDEuMi4xLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBhc2NlbmRpbmcgPSBmdW5jdGlvbihhLCBiKSB7XG4gIHJldHVybiBhIDwgYiA/IC0xIDogYSA+IGIgPyAxIDogYSA+PSBiID8gMCA6IE5hTjtcbn07XG5cbnZhciBiaXNlY3RvciA9IGZ1bmN0aW9uKGNvbXBhcmUpIHtcbiAgaWYgKGNvbXBhcmUubGVuZ3RoID09PSAxKSBjb21wYXJlID0gYXNjZW5kaW5nQ29tcGFyYXRvcihjb21wYXJlKTtcbiAgcmV0dXJuIHtcbiAgICBsZWZ0OiBmdW5jdGlvbihhLCB4LCBsbywgaGkpIHtcbiAgICAgIGlmIChsbyA9PSBudWxsKSBsbyA9IDA7XG4gICAgICBpZiAoaGkgPT0gbnVsbCkgaGkgPSBhLmxlbmd0aDtcbiAgICAgIHdoaWxlIChsbyA8IGhpKSB7XG4gICAgICAgIHZhciBtaWQgPSBsbyArIGhpID4+PiAxO1xuICAgICAgICBpZiAoY29tcGFyZShhW21pZF0sIHgpIDwgMCkgbG8gPSBtaWQgKyAxO1xuICAgICAgICBlbHNlIGhpID0gbWlkO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxvO1xuICAgIH0sXG4gICAgcmlnaHQ6IGZ1bmN0aW9uKGEsIHgsIGxvLCBoaSkge1xuICAgICAgaWYgKGxvID09IG51bGwpIGxvID0gMDtcbiAgICAgIGlmIChoaSA9PSBudWxsKSBoaSA9IGEubGVuZ3RoO1xuICAgICAgd2hpbGUgKGxvIDwgaGkpIHtcbiAgICAgICAgdmFyIG1pZCA9IGxvICsgaGkgPj4+IDE7XG4gICAgICAgIGlmIChjb21wYXJlKGFbbWlkXSwgeCkgPiAwKSBoaSA9IG1pZDtcbiAgICAgICAgZWxzZSBsbyA9IG1pZCArIDE7XG4gICAgICB9XG4gICAgICByZXR1cm4gbG87XG4gICAgfVxuICB9O1xufTtcblxuZnVuY3Rpb24gYXNjZW5kaW5nQ29tcGFyYXRvcihmKSB7XG4gIHJldHVybiBmdW5jdGlvbihkLCB4KSB7XG4gICAgcmV0dXJuIGFzY2VuZGluZyhmKGQpLCB4KTtcbiAgfTtcbn1cblxudmFyIGFzY2VuZGluZ0Jpc2VjdCA9IGJpc2VjdG9yKGFzY2VuZGluZyk7XG52YXIgYmlzZWN0UmlnaHQgPSBhc2NlbmRpbmdCaXNlY3QucmlnaHQ7XG52YXIgYmlzZWN0TGVmdCA9IGFzY2VuZGluZ0Jpc2VjdC5sZWZ0O1xuXG52YXIgcGFpcnMgPSBmdW5jdGlvbihhcnJheSwgZikge1xuICBpZiAoZiA9PSBudWxsKSBmID0gcGFpcjtcbiAgdmFyIGkgPSAwLCBuID0gYXJyYXkubGVuZ3RoIC0gMSwgcCA9IGFycmF5WzBdLCBwYWlycyA9IG5ldyBBcnJheShuIDwgMCA/IDAgOiBuKTtcbiAgd2hpbGUgKGkgPCBuKSBwYWlyc1tpXSA9IGYocCwgcCA9IGFycmF5WysraV0pO1xuICByZXR1cm4gcGFpcnM7XG59O1xuXG5mdW5jdGlvbiBwYWlyKGEsIGIpIHtcbiAgcmV0dXJuIFthLCBiXTtcbn1cblxudmFyIGNyb3NzID0gZnVuY3Rpb24odmFsdWVzMCwgdmFsdWVzMSwgcmVkdWNlKSB7XG4gIHZhciBuMCA9IHZhbHVlczAubGVuZ3RoLFxuICAgICAgbjEgPSB2YWx1ZXMxLmxlbmd0aCxcbiAgICAgIHZhbHVlcyA9IG5ldyBBcnJheShuMCAqIG4xKSxcbiAgICAgIGkwLFxuICAgICAgaTEsXG4gICAgICBpLFxuICAgICAgdmFsdWUwO1xuXG4gIGlmIChyZWR1Y2UgPT0gbnVsbCkgcmVkdWNlID0gcGFpcjtcblxuICBmb3IgKGkwID0gaSA9IDA7IGkwIDwgbjA7ICsraTApIHtcbiAgICBmb3IgKHZhbHVlMCA9IHZhbHVlczBbaTBdLCBpMSA9IDA7IGkxIDwgbjE7ICsraTEsICsraSkge1xuICAgICAgdmFsdWVzW2ldID0gcmVkdWNlKHZhbHVlMCwgdmFsdWVzMVtpMV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB2YWx1ZXM7XG59O1xuXG52YXIgZGVzY2VuZGluZyA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgcmV0dXJuIGIgPCBhID8gLTEgOiBiID4gYSA/IDEgOiBiID49IGEgPyAwIDogTmFOO1xufTtcblxudmFyIG51bWJlciA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGwgPyBOYU4gOiAreDtcbn07XG5cbnZhciB2YXJpYW5jZSA9IGZ1bmN0aW9uKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBtID0gMCxcbiAgICAgIGkgPSAtMSxcbiAgICAgIG1lYW4gPSAwLFxuICAgICAgdmFsdWUsXG4gICAgICBkZWx0YSxcbiAgICAgIHN1bSA9IDA7XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlID0gbnVtYmVyKHZhbHVlc1tpXSkpKSB7XG4gICAgICAgIGRlbHRhID0gdmFsdWUgLSBtZWFuO1xuICAgICAgICBtZWFuICs9IGRlbHRhIC8gKyttO1xuICAgICAgICBzdW0gKz0gZGVsdGEgKiAodmFsdWUgLSBtZWFuKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgaWYgKCFpc05hTih2YWx1ZSA9IG51bWJlcih2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkpKSB7XG4gICAgICAgIGRlbHRhID0gdmFsdWUgLSBtZWFuO1xuICAgICAgICBtZWFuICs9IGRlbHRhIC8gKyttO1xuICAgICAgICBzdW0gKz0gZGVsdGEgKiAodmFsdWUgLSBtZWFuKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAobSA+IDEpIHJldHVybiBzdW0gLyAobSAtIDEpO1xufTtcblxudmFyIGRldmlhdGlvbiA9IGZ1bmN0aW9uKGFycmF5LCBmKSB7XG4gIHZhciB2ID0gdmFyaWFuY2UoYXJyYXksIGYpO1xuICByZXR1cm4gdiA/IE1hdGguc3FydCh2KSA6IHY7XG59O1xuXG52YXIgZXh0ZW50ID0gZnVuY3Rpb24odmFsdWVzLCB2YWx1ZW9mKSB7XG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgbWluLFxuICAgICAgbWF4O1xuXG4gIGlmICh2YWx1ZW9mID09IG51bGwpIHtcbiAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBGaW5kIHRoZSBmaXJzdCBjb21wYXJhYmxlIHZhbHVlLlxuICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlc1tpXSkgIT0gbnVsbCAmJiB2YWx1ZSA+PSB2YWx1ZSkge1xuICAgICAgICBtaW4gPSBtYXggPSB2YWx1ZTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHsgLy8gQ29tcGFyZSB0aGUgcmVtYWluaW5nIHZhbHVlcy5cbiAgICAgICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAobWluID4gdmFsdWUpIG1pbiA9IHZhbHVlO1xuICAgICAgICAgICAgaWYgKG1heCA8IHZhbHVlKSBtYXggPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlbHNlIHtcbiAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBGaW5kIHRoZSBmaXJzdCBjb21wYXJhYmxlIHZhbHVlLlxuICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1pbiA9IG1heCA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKG1pbiA+IHZhbHVlKSBtaW4gPSB2YWx1ZTtcbiAgICAgICAgICAgIGlmIChtYXggPCB2YWx1ZSkgbWF4ID0gdmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFttaW4sIG1heF07XG59O1xuXG52YXIgYXJyYXkgPSBBcnJheS5wcm90b3R5cGU7XG5cbnZhciBzbGljZSA9IGFycmF5LnNsaWNlO1xudmFyIG1hcCA9IGFycmF5Lm1hcDtcblxudmFyIGNvbnN0YW50ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59O1xuXG52YXIgaWRlbnRpdHkgPSBmdW5jdGlvbih4KSB7XG4gIHJldHVybiB4O1xufTtcblxudmFyIHJhbmdlID0gZnVuY3Rpb24oc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgc3RhcnQgPSArc3RhcnQsIHN0b3AgPSArc3RvcCwgc3RlcCA9IChuID0gYXJndW1lbnRzLmxlbmd0aCkgPCAyID8gKHN0b3AgPSBzdGFydCwgc3RhcnQgPSAwLCAxKSA6IG4gPCAzID8gMSA6ICtzdGVwO1xuXG4gIHZhciBpID0gLTEsXG4gICAgICBuID0gTWF0aC5tYXgoMCwgTWF0aC5jZWlsKChzdG9wIC0gc3RhcnQpIC8gc3RlcCkpIHwgMCxcbiAgICAgIHJhbmdlID0gbmV3IEFycmF5KG4pO1xuXG4gIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgcmFuZ2VbaV0gPSBzdGFydCArIGkgKiBzdGVwO1xuICB9XG5cbiAgcmV0dXJuIHJhbmdlO1xufTtcblxudmFyIGUxMCA9IE1hdGguc3FydCg1MCk7XG52YXIgZTUgPSBNYXRoLnNxcnQoMTApO1xudmFyIGUyID0gTWF0aC5zcXJ0KDIpO1xuXG52YXIgdGlja3MgPSBmdW5jdGlvbihzdGFydCwgc3RvcCwgY291bnQpIHtcbiAgdmFyIHJldmVyc2UsXG4gICAgICBpID0gLTEsXG4gICAgICBuLFxuICAgICAgdGlja3MsXG4gICAgICBzdGVwO1xuXG4gIHN0b3AgPSArc3RvcCwgc3RhcnQgPSArc3RhcnQsIGNvdW50ID0gK2NvdW50O1xuICBpZiAoc3RhcnQgPT09IHN0b3AgJiYgY291bnQgPiAwKSByZXR1cm4gW3N0YXJ0XTtcbiAgaWYgKHJldmVyc2UgPSBzdG9wIDwgc3RhcnQpIG4gPSBzdGFydCwgc3RhcnQgPSBzdG9wLCBzdG9wID0gbjtcbiAgaWYgKChzdGVwID0gdGlja0luY3JlbWVudChzdGFydCwgc3RvcCwgY291bnQpKSA9PT0gMCB8fCAhaXNGaW5pdGUoc3RlcCkpIHJldHVybiBbXTtcblxuICBpZiAoc3RlcCA+IDApIHtcbiAgICBzdGFydCA9IE1hdGguY2VpbChzdGFydCAvIHN0ZXApO1xuICAgIHN0b3AgPSBNYXRoLmZsb29yKHN0b3AgLyBzdGVwKTtcbiAgICB0aWNrcyA9IG5ldyBBcnJheShuID0gTWF0aC5jZWlsKHN0b3AgLSBzdGFydCArIDEpKTtcbiAgICB3aGlsZSAoKytpIDwgbikgdGlja3NbaV0gPSAoc3RhcnQgKyBpKSAqIHN0ZXA7XG4gIH0gZWxzZSB7XG4gICAgc3RhcnQgPSBNYXRoLmZsb29yKHN0YXJ0ICogc3RlcCk7XG4gICAgc3RvcCA9IE1hdGguY2VpbChzdG9wICogc3RlcCk7XG4gICAgdGlja3MgPSBuZXcgQXJyYXkobiA9IE1hdGguY2VpbChzdGFydCAtIHN0b3AgKyAxKSk7XG4gICAgd2hpbGUgKCsraSA8IG4pIHRpY2tzW2ldID0gKHN0YXJ0IC0gaSkgLyBzdGVwO1xuICB9XG5cbiAgaWYgKHJldmVyc2UpIHRpY2tzLnJldmVyc2UoKTtcblxuICByZXR1cm4gdGlja3M7XG59O1xuXG5mdW5jdGlvbiB0aWNrSW5jcmVtZW50KHN0YXJ0LCBzdG9wLCBjb3VudCkge1xuICB2YXIgc3RlcCA9IChzdG9wIC0gc3RhcnQpIC8gTWF0aC5tYXgoMCwgY291bnQpLFxuICAgICAgcG93ZXIgPSBNYXRoLmZsb29yKE1hdGgubG9nKHN0ZXApIC8gTWF0aC5MTjEwKSxcbiAgICAgIGVycm9yID0gc3RlcCAvIE1hdGgucG93KDEwLCBwb3dlcik7XG4gIHJldHVybiBwb3dlciA+PSAwXG4gICAgICA/IChlcnJvciA+PSBlMTAgPyAxMCA6IGVycm9yID49IGU1ID8gNSA6IGVycm9yID49IGUyID8gMiA6IDEpICogTWF0aC5wb3coMTAsIHBvd2VyKVxuICAgICAgOiAtTWF0aC5wb3coMTAsIC1wb3dlcikgLyAoZXJyb3IgPj0gZTEwID8gMTAgOiBlcnJvciA+PSBlNSA/IDUgOiBlcnJvciA+PSBlMiA/IDIgOiAxKTtcbn1cblxuZnVuY3Rpb24gdGlja1N0ZXAoc3RhcnQsIHN0b3AsIGNvdW50KSB7XG4gIHZhciBzdGVwMCA9IE1hdGguYWJzKHN0b3AgLSBzdGFydCkgLyBNYXRoLm1heCgwLCBjb3VudCksXG4gICAgICBzdGVwMSA9IE1hdGgucG93KDEwLCBNYXRoLmZsb29yKE1hdGgubG9nKHN0ZXAwKSAvIE1hdGguTE4xMCkpLFxuICAgICAgZXJyb3IgPSBzdGVwMCAvIHN0ZXAxO1xuICBpZiAoZXJyb3IgPj0gZTEwKSBzdGVwMSAqPSAxMDtcbiAgZWxzZSBpZiAoZXJyb3IgPj0gZTUpIHN0ZXAxICo9IDU7XG4gIGVsc2UgaWYgKGVycm9yID49IGUyKSBzdGVwMSAqPSAyO1xuICByZXR1cm4gc3RvcCA8IHN0YXJ0ID8gLXN0ZXAxIDogc3RlcDE7XG59XG5cbnZhciBzdHVyZ2VzID0gZnVuY3Rpb24odmFsdWVzKSB7XG4gIHJldHVybiBNYXRoLmNlaWwoTWF0aC5sb2codmFsdWVzLmxlbmd0aCkgLyBNYXRoLkxOMikgKyAxO1xufTtcblxudmFyIGhpc3RvZ3JhbSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgdmFsdWUgPSBpZGVudGl0eSxcbiAgICAgIGRvbWFpbiA9IGV4dGVudCxcbiAgICAgIHRocmVzaG9sZCA9IHN0dXJnZXM7XG5cbiAgZnVuY3Rpb24gaGlzdG9ncmFtKGRhdGEpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgbiA9IGRhdGEubGVuZ3RoLFxuICAgICAgICB4LFxuICAgICAgICB2YWx1ZXMgPSBuZXcgQXJyYXkobik7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YWx1ZXNbaV0gPSB2YWx1ZShkYXRhW2ldLCBpLCBkYXRhKTtcbiAgICB9XG5cbiAgICB2YXIgeHogPSBkb21haW4odmFsdWVzKSxcbiAgICAgICAgeDAgPSB4elswXSxcbiAgICAgICAgeDEgPSB4elsxXSxcbiAgICAgICAgdHogPSB0aHJlc2hvbGQodmFsdWVzLCB4MCwgeDEpO1xuXG4gICAgLy8gQ29udmVydCBudW1iZXIgb2YgdGhyZXNob2xkcyBpbnRvIHVuaWZvcm0gdGhyZXNob2xkcy5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodHopKSB7XG4gICAgICB0eiA9IHRpY2tTdGVwKHgwLCB4MSwgdHopO1xuICAgICAgdHogPSByYW5nZShNYXRoLmNlaWwoeDAgLyB0eikgKiB0eiwgTWF0aC5mbG9vcih4MSAvIHR6KSAqIHR6LCB0eik7IC8vIGV4Y2x1c2l2ZVxuICAgIH1cblxuICAgIC8vIFJlbW92ZSBhbnkgdGhyZXNob2xkcyBvdXRzaWRlIHRoZSBkb21haW4uXG4gICAgdmFyIG0gPSB0ei5sZW5ndGg7XG4gICAgd2hpbGUgKHR6WzBdIDw9IHgwKSB0ei5zaGlmdCgpLCAtLW07XG4gICAgd2hpbGUgKHR6W20gLSAxXSA+IHgxKSB0ei5wb3AoKSwgLS1tO1xuXG4gICAgdmFyIGJpbnMgPSBuZXcgQXJyYXkobSArIDEpLFxuICAgICAgICBiaW47XG5cbiAgICAvLyBJbml0aWFsaXplIGJpbnMuXG4gICAgZm9yIChpID0gMDsgaSA8PSBtOyArK2kpIHtcbiAgICAgIGJpbiA9IGJpbnNbaV0gPSBbXTtcbiAgICAgIGJpbi54MCA9IGkgPiAwID8gdHpbaSAtIDFdIDogeDA7XG4gICAgICBiaW4ueDEgPSBpIDwgbSA/IHR6W2ldIDogeDE7XG4gICAgfVxuXG4gICAgLy8gQXNzaWduIGRhdGEgdG8gYmlucyBieSB2YWx1ZSwgaWdub3JpbmcgYW55IG91dHNpZGUgdGhlIGRvbWFpbi5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICB4ID0gdmFsdWVzW2ldO1xuICAgICAgaWYgKHgwIDw9IHggJiYgeCA8PSB4MSkge1xuICAgICAgICBiaW5zW2Jpc2VjdFJpZ2h0KHR6LCB4LCAwLCBtKV0ucHVzaChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYmlucztcbiAgfVxuXG4gIGhpc3RvZ3JhbS52YWx1ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoXyksIGhpc3RvZ3JhbSkgOiB2YWx1ZTtcbiAgfTtcblxuICBoaXN0b2dyYW0uZG9tYWluID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRvbWFpbiA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoW19bMF0sIF9bMV1dKSwgaGlzdG9ncmFtKSA6IGRvbWFpbjtcbiAgfTtcblxuICBoaXN0b2dyYW0udGhyZXNob2xkcyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aHJlc2hvbGQgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IEFycmF5LmlzQXJyYXkoXykgPyBjb25zdGFudChzbGljZS5jYWxsKF8pKSA6IGNvbnN0YW50KF8pLCBoaXN0b2dyYW0pIDogdGhyZXNob2xkO1xuICB9O1xuXG4gIHJldHVybiBoaXN0b2dyYW07XG59O1xuXG52YXIgcXVhbnRpbGUgPSBmdW5jdGlvbih2YWx1ZXMsIHAsIHZhbHVlb2YpIHtcbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkgdmFsdWVvZiA9IG51bWJlcjtcbiAgaWYgKCEobiA9IHZhbHVlcy5sZW5ndGgpKSByZXR1cm47XG4gIGlmICgocCA9ICtwKSA8PSAwIHx8IG4gPCAyKSByZXR1cm4gK3ZhbHVlb2YodmFsdWVzWzBdLCAwLCB2YWx1ZXMpO1xuICBpZiAocCA+PSAxKSByZXR1cm4gK3ZhbHVlb2YodmFsdWVzW24gLSAxXSwgbiAtIDEsIHZhbHVlcyk7XG4gIHZhciBuLFxuICAgICAgaSA9IChuIC0gMSkgKiBwLFxuICAgICAgaTAgPSBNYXRoLmZsb29yKGkpLFxuICAgICAgdmFsdWUwID0gK3ZhbHVlb2YodmFsdWVzW2kwXSwgaTAsIHZhbHVlcyksXG4gICAgICB2YWx1ZTEgPSArdmFsdWVvZih2YWx1ZXNbaTAgKyAxXSwgaTAgKyAxLCB2YWx1ZXMpO1xuICByZXR1cm4gdmFsdWUwICsgKHZhbHVlMSAtIHZhbHVlMCkgKiAoaSAtIGkwKTtcbn07XG5cbnZhciBmcmVlZG1hbkRpYWNvbmlzID0gZnVuY3Rpb24odmFsdWVzLCBtaW4sIG1heCkge1xuICB2YWx1ZXMgPSBtYXAuY2FsbCh2YWx1ZXMsIG51bWJlcikuc29ydChhc2NlbmRpbmcpO1xuICByZXR1cm4gTWF0aC5jZWlsKChtYXggLSBtaW4pIC8gKDIgKiAocXVhbnRpbGUodmFsdWVzLCAwLjc1KSAtIHF1YW50aWxlKHZhbHVlcywgMC4yNSkpICogTWF0aC5wb3codmFsdWVzLmxlbmd0aCwgLTEgLyAzKSkpO1xufTtcblxudmFyIHNjb3R0ID0gZnVuY3Rpb24odmFsdWVzLCBtaW4sIG1heCkge1xuICByZXR1cm4gTWF0aC5jZWlsKChtYXggLSBtaW4pIC8gKDMuNSAqIGRldmlhdGlvbih2YWx1ZXMpICogTWF0aC5wb3codmFsdWVzLmxlbmd0aCwgLTEgLyAzKSkpO1xufTtcblxudmFyIG1heCA9IGZ1bmN0aW9uKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBpID0gLTEsXG4gICAgICB2YWx1ZSxcbiAgICAgIG1heDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHsgLy8gRmluZCB0aGUgZmlyc3QgY29tcGFyYWJsZSB2YWx1ZS5cbiAgICAgIGlmICgodmFsdWUgPSB2YWx1ZXNbaV0pICE9IG51bGwgJiYgdmFsdWUgPj0gdmFsdWUpIHtcbiAgICAgICAgbWF4ID0gdmFsdWU7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIENvbXBhcmUgdGhlIHJlbWFpbmluZyB2YWx1ZXMuXG4gICAgICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlc1tpXSkgIT0gbnVsbCAmJiB2YWx1ZSA+IG1heCkge1xuICAgICAgICAgICAgbWF4ID0gdmFsdWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZWxzZSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHsgLy8gRmluZCB0aGUgZmlyc3QgY29tcGFyYWJsZSB2YWx1ZS5cbiAgICAgIGlmICgodmFsdWUgPSB2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkgIT0gbnVsbCAmJiB2YWx1ZSA+PSB2YWx1ZSkge1xuICAgICAgICBtYXggPSB2YWx1ZTtcbiAgICAgICAgd2hpbGUgKCsraSA8IG4pIHsgLy8gQ29tcGFyZSB0aGUgcmVtYWluaW5nIHZhbHVlcy5cbiAgICAgICAgICBpZiAoKHZhbHVlID0gdmFsdWVvZih2YWx1ZXNbaV0sIGksIHZhbHVlcykpICE9IG51bGwgJiYgdmFsdWUgPiBtYXgpIHtcbiAgICAgICAgICAgIG1heCA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtYXg7XG59O1xuXG52YXIgbWVhbiA9IGZ1bmN0aW9uKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBtID0gbixcbiAgICAgIGkgPSAtMSxcbiAgICAgIHZhbHVlLFxuICAgICAgc3VtID0gMDtcblxuICBpZiAodmFsdWVvZiA9PSBudWxsKSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVzW2ldKSkpIHN1bSArPSB2YWx1ZTtcbiAgICAgIGVsc2UgLS1tO1xuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlID0gbnVtYmVyKHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSkpIHN1bSArPSB2YWx1ZTtcbiAgICAgIGVsc2UgLS1tO1xuICAgIH1cbiAgfVxuXG4gIGlmIChtKSByZXR1cm4gc3VtIC8gbTtcbn07XG5cbnZhciBtZWRpYW4gPSBmdW5jdGlvbih2YWx1ZXMsIHZhbHVlb2YpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgaSA9IC0xLFxuICAgICAgdmFsdWUsXG4gICAgICBudW1iZXJzID0gW107XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAoIWlzTmFOKHZhbHVlID0gbnVtYmVyKHZhbHVlc1tpXSkpKSB7XG4gICAgICAgIG51bWJlcnMucHVzaCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZWxzZSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICghaXNOYU4odmFsdWUgPSBudW1iZXIodmFsdWVvZih2YWx1ZXNbaV0sIGksIHZhbHVlcykpKSkge1xuICAgICAgICBudW1iZXJzLnB1c2godmFsdWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBxdWFudGlsZShudW1iZXJzLnNvcnQoYXNjZW5kaW5nKSwgMC41KTtcbn07XG5cbnZhciBtZXJnZSA9IGZ1bmN0aW9uKGFycmF5cykge1xuICB2YXIgbiA9IGFycmF5cy5sZW5ndGgsXG4gICAgICBtLFxuICAgICAgaSA9IC0xLFxuICAgICAgaiA9IDAsXG4gICAgICBtZXJnZWQsXG4gICAgICBhcnJheTtcblxuICB3aGlsZSAoKytpIDwgbikgaiArPSBhcnJheXNbaV0ubGVuZ3RoO1xuICBtZXJnZWQgPSBuZXcgQXJyYXkoaik7XG5cbiAgd2hpbGUgKC0tbiA+PSAwKSB7XG4gICAgYXJyYXkgPSBhcnJheXNbbl07XG4gICAgbSA9IGFycmF5Lmxlbmd0aDtcbiAgICB3aGlsZSAoLS1tID49IDApIHtcbiAgICAgIG1lcmdlZFstLWpdID0gYXJyYXlbbV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1lcmdlZDtcbn07XG5cbnZhciBtaW4gPSBmdW5jdGlvbih2YWx1ZXMsIHZhbHVlb2YpIHtcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoLFxuICAgICAgaSA9IC0xLFxuICAgICAgdmFsdWUsXG4gICAgICBtaW47XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVzW2ldKSAhPSBudWxsICYmIHZhbHVlID49IHZhbHVlKSB7XG4gICAgICAgIG1pbiA9IHZhbHVlO1xuICAgICAgICB3aGlsZSAoKytpIDwgbikgeyAvLyBDb21wYXJlIHRoZSByZW1haW5pbmcgdmFsdWVzLlxuICAgICAgICAgIGlmICgodmFsdWUgPSB2YWx1ZXNbaV0pICE9IG51bGwgJiYgbWluID4gdmFsdWUpIHtcbiAgICAgICAgICAgIG1pbiA9IHZhbHVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGVsc2Uge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIEZpbmQgdGhlIGZpcnN0IGNvbXBhcmFibGUgdmFsdWUuXG4gICAgICBpZiAoKHZhbHVlID0gdmFsdWVvZih2YWx1ZXNbaV0sIGksIHZhbHVlcykpICE9IG51bGwgJiYgdmFsdWUgPj0gdmFsdWUpIHtcbiAgICAgICAgbWluID0gdmFsdWU7XG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7IC8vIENvbXBhcmUgdGhlIHJlbWFpbmluZyB2YWx1ZXMuXG4gICAgICAgICAgaWYgKCh2YWx1ZSA9IHZhbHVlb2YodmFsdWVzW2ldLCBpLCB2YWx1ZXMpKSAhPSBudWxsICYmIG1pbiA+IHZhbHVlKSB7XG4gICAgICAgICAgICBtaW4gPSB2YWx1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWluO1xufTtcblxudmFyIHBlcm11dGUgPSBmdW5jdGlvbihhcnJheSwgaW5kZXhlcykge1xuICB2YXIgaSA9IGluZGV4ZXMubGVuZ3RoLCBwZXJtdXRlcyA9IG5ldyBBcnJheShpKTtcbiAgd2hpbGUgKGktLSkgcGVybXV0ZXNbaV0gPSBhcnJheVtpbmRleGVzW2ldXTtcbiAgcmV0dXJuIHBlcm11dGVzO1xufTtcblxudmFyIHNjYW4gPSBmdW5jdGlvbih2YWx1ZXMsIGNvbXBhcmUpIHtcbiAgaWYgKCEobiA9IHZhbHVlcy5sZW5ndGgpKSByZXR1cm47XG4gIHZhciBuLFxuICAgICAgaSA9IDAsXG4gICAgICBqID0gMCxcbiAgICAgIHhpLFxuICAgICAgeGogPSB2YWx1ZXNbal07XG5cbiAgaWYgKGNvbXBhcmUgPT0gbnVsbCkgY29tcGFyZSA9IGFzY2VuZGluZztcblxuICB3aGlsZSAoKytpIDwgbikge1xuICAgIGlmIChjb21wYXJlKHhpID0gdmFsdWVzW2ldLCB4aikgPCAwIHx8IGNvbXBhcmUoeGosIHhqKSAhPT0gMCkge1xuICAgICAgeGogPSB4aSwgaiA9IGk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGNvbXBhcmUoeGosIHhqKSA9PT0gMCkgcmV0dXJuIGo7XG59O1xuXG52YXIgc2h1ZmZsZSA9IGZ1bmN0aW9uKGFycmF5LCBpMCwgaTEpIHtcbiAgdmFyIG0gPSAoaTEgPT0gbnVsbCA/IGFycmF5Lmxlbmd0aCA6IGkxKSAtIChpMCA9IGkwID09IG51bGwgPyAwIDogK2kwKSxcbiAgICAgIHQsXG4gICAgICBpO1xuXG4gIHdoaWxlIChtKSB7XG4gICAgaSA9IE1hdGgucmFuZG9tKCkgKiBtLS0gfCAwO1xuICAgIHQgPSBhcnJheVttICsgaTBdO1xuICAgIGFycmF5W20gKyBpMF0gPSBhcnJheVtpICsgaTBdO1xuICAgIGFycmF5W2kgKyBpMF0gPSB0O1xuICB9XG5cbiAgcmV0dXJuIGFycmF5O1xufTtcblxudmFyIHN1bSA9IGZ1bmN0aW9uKHZhbHVlcywgdmFsdWVvZikge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGgsXG4gICAgICBpID0gLTEsXG4gICAgICB2YWx1ZSxcbiAgICAgIHN1bSA9IDA7XG5cbiAgaWYgKHZhbHVlb2YgPT0gbnVsbCkge1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAodmFsdWUgPSArdmFsdWVzW2ldKSBzdW0gKz0gdmFsdWU7IC8vIE5vdGU6IHplcm8gYW5kIG51bGwgYXJlIGVxdWl2YWxlbnQuXG4gICAgfVxuICB9XG5cbiAgZWxzZSB7XG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICh2YWx1ZSA9ICt2YWx1ZW9mKHZhbHVlc1tpXSwgaSwgdmFsdWVzKSkgc3VtICs9IHZhbHVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdW07XG59O1xuXG52YXIgdHJhbnNwb3NlID0gZnVuY3Rpb24obWF0cml4KSB7XG4gIGlmICghKG4gPSBtYXRyaXgubGVuZ3RoKSkgcmV0dXJuIFtdO1xuICBmb3IgKHZhciBpID0gLTEsIG0gPSBtaW4obWF0cml4LCBsZW5ndGgpLCB0cmFuc3Bvc2UgPSBuZXcgQXJyYXkobSk7ICsraSA8IG07KSB7XG4gICAgZm9yICh2YXIgaiA9IC0xLCBuLCByb3cgPSB0cmFuc3Bvc2VbaV0gPSBuZXcgQXJyYXkobik7ICsraiA8IG47KSB7XG4gICAgICByb3dbal0gPSBtYXRyaXhbal1baV07XG4gICAgfVxuICB9XG4gIHJldHVybiB0cmFuc3Bvc2U7XG59O1xuXG5mdW5jdGlvbiBsZW5ndGgoZCkge1xuICByZXR1cm4gZC5sZW5ndGg7XG59XG5cbnZhciB6aXAgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRyYW5zcG9zZShhcmd1bWVudHMpO1xufTtcblxuZXhwb3J0cy5iaXNlY3QgPSBiaXNlY3RSaWdodDtcbmV4cG9ydHMuYmlzZWN0UmlnaHQgPSBiaXNlY3RSaWdodDtcbmV4cG9ydHMuYmlzZWN0TGVmdCA9IGJpc2VjdExlZnQ7XG5leHBvcnRzLmFzY2VuZGluZyA9IGFzY2VuZGluZztcbmV4cG9ydHMuYmlzZWN0b3IgPSBiaXNlY3RvcjtcbmV4cG9ydHMuY3Jvc3MgPSBjcm9zcztcbmV4cG9ydHMuZGVzY2VuZGluZyA9IGRlc2NlbmRpbmc7XG5leHBvcnRzLmRldmlhdGlvbiA9IGRldmlhdGlvbjtcbmV4cG9ydHMuZXh0ZW50ID0gZXh0ZW50O1xuZXhwb3J0cy5oaXN0b2dyYW0gPSBoaXN0b2dyYW07XG5leHBvcnRzLnRocmVzaG9sZEZyZWVkbWFuRGlhY29uaXMgPSBmcmVlZG1hbkRpYWNvbmlzO1xuZXhwb3J0cy50aHJlc2hvbGRTY290dCA9IHNjb3R0O1xuZXhwb3J0cy50aHJlc2hvbGRTdHVyZ2VzID0gc3R1cmdlcztcbmV4cG9ydHMubWF4ID0gbWF4O1xuZXhwb3J0cy5tZWFuID0gbWVhbjtcbmV4cG9ydHMubWVkaWFuID0gbWVkaWFuO1xuZXhwb3J0cy5tZXJnZSA9IG1lcmdlO1xuZXhwb3J0cy5taW4gPSBtaW47XG5leHBvcnRzLnBhaXJzID0gcGFpcnM7XG5leHBvcnRzLnBlcm11dGUgPSBwZXJtdXRlO1xuZXhwb3J0cy5xdWFudGlsZSA9IHF1YW50aWxlO1xuZXhwb3J0cy5yYW5nZSA9IHJhbmdlO1xuZXhwb3J0cy5zY2FuID0gc2NhbjtcbmV4cG9ydHMuc2h1ZmZsZSA9IHNodWZmbGU7XG5leHBvcnRzLnN1bSA9IHN1bTtcbmV4cG9ydHMudGlja3MgPSB0aWNrcztcbmV4cG9ydHMudGlja0luY3JlbWVudCA9IHRpY2tJbmNyZW1lbnQ7XG5leHBvcnRzLnRpY2tTdGVwID0gdGlja1N0ZXA7XG5leHBvcnRzLnRyYW5zcG9zZSA9IHRyYW5zcG9zZTtcbmV4cG9ydHMudmFyaWFuY2UgPSB2YXJpYW5jZTtcbmV4cG9ydHMuemlwID0gemlwO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1heGlzLyBWZXJzaW9uIDEuMC44LiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcblxudmFyIGlkZW50aXR5ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4geDtcbn07XG5cbnZhciB0b3AgPSAxO1xudmFyIHJpZ2h0ID0gMjtcbnZhciBib3R0b20gPSAzO1xudmFyIGxlZnQgPSA0O1xudmFyIGVwc2lsb24gPSAxZS02O1xuXG5mdW5jdGlvbiB0cmFuc2xhdGVYKHgpIHtcbiAgcmV0dXJuIFwidHJhbnNsYXRlKFwiICsgKHggKyAwLjUpICsgXCIsMClcIjtcbn1cblxuZnVuY3Rpb24gdHJhbnNsYXRlWSh5KSB7XG4gIHJldHVybiBcInRyYW5zbGF0ZSgwLFwiICsgKHkgKyAwLjUpICsgXCIpXCI7XG59XG5cbmZ1bmN0aW9uIG51bWJlcihzY2FsZSkge1xuICByZXR1cm4gZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiArc2NhbGUoZCk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGNlbnRlcihzY2FsZSkge1xuICB2YXIgb2Zmc2V0ID0gTWF0aC5tYXgoMCwgc2NhbGUuYmFuZHdpZHRoKCkgLSAxKSAvIDI7IC8vIEFkanVzdCBmb3IgMC41cHggb2Zmc2V0LlxuICBpZiAoc2NhbGUucm91bmQoKSkgb2Zmc2V0ID0gTWF0aC5yb3VuZChvZmZzZXQpO1xuICByZXR1cm4gZnVuY3Rpb24oZCkge1xuICAgIHJldHVybiArc2NhbGUoZCkgKyBvZmZzZXQ7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGVudGVyaW5nKCkge1xuICByZXR1cm4gIXRoaXMuX19heGlzO1xufVxuXG5mdW5jdGlvbiBheGlzKG9yaWVudCwgc2NhbGUpIHtcbiAgdmFyIHRpY2tBcmd1bWVudHMgPSBbXSxcbiAgICAgIHRpY2tWYWx1ZXMgPSBudWxsLFxuICAgICAgdGlja0Zvcm1hdCA9IG51bGwsXG4gICAgICB0aWNrU2l6ZUlubmVyID0gNixcbiAgICAgIHRpY2tTaXplT3V0ZXIgPSA2LFxuICAgICAgdGlja1BhZGRpbmcgPSAzLFxuICAgICAgayA9IG9yaWVudCA9PT0gdG9wIHx8IG9yaWVudCA9PT0gbGVmdCA/IC0xIDogMSxcbiAgICAgIHggPSBvcmllbnQgPT09IGxlZnQgfHwgb3JpZW50ID09PSByaWdodCA/IFwieFwiIDogXCJ5XCIsXG4gICAgICB0cmFuc2Zvcm0gPSBvcmllbnQgPT09IHRvcCB8fCBvcmllbnQgPT09IGJvdHRvbSA/IHRyYW5zbGF0ZVggOiB0cmFuc2xhdGVZO1xuXG4gIGZ1bmN0aW9uIGF4aXMoY29udGV4dCkge1xuICAgIHZhciB2YWx1ZXMgPSB0aWNrVmFsdWVzID09IG51bGwgPyAoc2NhbGUudGlja3MgPyBzY2FsZS50aWNrcy5hcHBseShzY2FsZSwgdGlja0FyZ3VtZW50cykgOiBzY2FsZS5kb21haW4oKSkgOiB0aWNrVmFsdWVzLFxuICAgICAgICBmb3JtYXQgPSB0aWNrRm9ybWF0ID09IG51bGwgPyAoc2NhbGUudGlja0Zvcm1hdCA/IHNjYWxlLnRpY2tGb3JtYXQuYXBwbHkoc2NhbGUsIHRpY2tBcmd1bWVudHMpIDogaWRlbnRpdHkpIDogdGlja0Zvcm1hdCxcbiAgICAgICAgc3BhY2luZyA9IE1hdGgubWF4KHRpY2tTaXplSW5uZXIsIDApICsgdGlja1BhZGRpbmcsXG4gICAgICAgIHJhbmdlID0gc2NhbGUucmFuZ2UoKSxcbiAgICAgICAgcmFuZ2UwID0gK3JhbmdlWzBdICsgMC41LFxuICAgICAgICByYW5nZTEgPSArcmFuZ2VbcmFuZ2UubGVuZ3RoIC0gMV0gKyAwLjUsXG4gICAgICAgIHBvc2l0aW9uID0gKHNjYWxlLmJhbmR3aWR0aCA/IGNlbnRlciA6IG51bWJlcikoc2NhbGUuY29weSgpKSxcbiAgICAgICAgc2VsZWN0aW9uID0gY29udGV4dC5zZWxlY3Rpb24gPyBjb250ZXh0LnNlbGVjdGlvbigpIDogY29udGV4dCxcbiAgICAgICAgcGF0aCA9IHNlbGVjdGlvbi5zZWxlY3RBbGwoXCIuZG9tYWluXCIpLmRhdGEoW251bGxdKSxcbiAgICAgICAgdGljayA9IHNlbGVjdGlvbi5zZWxlY3RBbGwoXCIudGlja1wiKS5kYXRhKHZhbHVlcywgc2NhbGUpLm9yZGVyKCksXG4gICAgICAgIHRpY2tFeGl0ID0gdGljay5leGl0KCksXG4gICAgICAgIHRpY2tFbnRlciA9IHRpY2suZW50ZXIoKS5hcHBlbmQoXCJnXCIpLmF0dHIoXCJjbGFzc1wiLCBcInRpY2tcIiksXG4gICAgICAgIGxpbmUgPSB0aWNrLnNlbGVjdChcImxpbmVcIiksXG4gICAgICAgIHRleHQgPSB0aWNrLnNlbGVjdChcInRleHRcIik7XG5cbiAgICBwYXRoID0gcGF0aC5tZXJnZShwYXRoLmVudGVyKCkuaW5zZXJ0KFwicGF0aFwiLCBcIi50aWNrXCIpXG4gICAgICAgIC5hdHRyKFwiY2xhc3NcIiwgXCJkb21haW5cIilcbiAgICAgICAgLmF0dHIoXCJzdHJva2VcIiwgXCIjMDAwXCIpKTtcblxuICAgIHRpY2sgPSB0aWNrLm1lcmdlKHRpY2tFbnRlcik7XG5cbiAgICBsaW5lID0gbGluZS5tZXJnZSh0aWNrRW50ZXIuYXBwZW5kKFwibGluZVwiKVxuICAgICAgICAuYXR0cihcInN0cm9rZVwiLCBcIiMwMDBcIilcbiAgICAgICAgLmF0dHIoeCArIFwiMlwiLCBrICogdGlja1NpemVJbm5lcikpO1xuXG4gICAgdGV4dCA9IHRleHQubWVyZ2UodGlja0VudGVyLmFwcGVuZChcInRleHRcIilcbiAgICAgICAgLmF0dHIoXCJmaWxsXCIsIFwiIzAwMFwiKVxuICAgICAgICAuYXR0cih4LCBrICogc3BhY2luZylcbiAgICAgICAgLmF0dHIoXCJkeVwiLCBvcmllbnQgPT09IHRvcCA/IFwiMGVtXCIgOiBvcmllbnQgPT09IGJvdHRvbSA/IFwiMC43MWVtXCIgOiBcIjAuMzJlbVwiKSk7XG5cbiAgICBpZiAoY29udGV4dCAhPT0gc2VsZWN0aW9uKSB7XG4gICAgICBwYXRoID0gcGF0aC50cmFuc2l0aW9uKGNvbnRleHQpO1xuICAgICAgdGljayA9IHRpY2sudHJhbnNpdGlvbihjb250ZXh0KTtcbiAgICAgIGxpbmUgPSBsaW5lLnRyYW5zaXRpb24oY29udGV4dCk7XG4gICAgICB0ZXh0ID0gdGV4dC50cmFuc2l0aW9uKGNvbnRleHQpO1xuXG4gICAgICB0aWNrRXhpdCA9IHRpY2tFeGl0LnRyYW5zaXRpb24oY29udGV4dClcbiAgICAgICAgICAuYXR0cihcIm9wYWNpdHlcIiwgZXBzaWxvbilcbiAgICAgICAgICAuYXR0cihcInRyYW5zZm9ybVwiLCBmdW5jdGlvbihkKSB7IHJldHVybiBpc0Zpbml0ZShkID0gcG9zaXRpb24oZCkpID8gdHJhbnNmb3JtKGQpIDogdGhpcy5nZXRBdHRyaWJ1dGUoXCJ0cmFuc2Zvcm1cIik7IH0pO1xuXG4gICAgICB0aWNrRW50ZXJcbiAgICAgICAgICAuYXR0cihcIm9wYWNpdHlcIiwgZXBzaWxvbilcbiAgICAgICAgICAuYXR0cihcInRyYW5zZm9ybVwiLCBmdW5jdGlvbihkKSB7IHZhciBwID0gdGhpcy5wYXJlbnROb2RlLl9fYXhpczsgcmV0dXJuIHRyYW5zZm9ybShwICYmIGlzRmluaXRlKHAgPSBwKGQpKSA/IHAgOiBwb3NpdGlvbihkKSk7IH0pO1xuICAgIH1cblxuICAgIHRpY2tFeGl0LnJlbW92ZSgpO1xuXG4gICAgcGF0aFxuICAgICAgICAuYXR0cihcImRcIiwgb3JpZW50ID09PSBsZWZ0IHx8IG9yaWVudCA9PSByaWdodFxuICAgICAgICAgICAgPyBcIk1cIiArIGsgKiB0aWNrU2l6ZU91dGVyICsgXCIsXCIgKyByYW5nZTAgKyBcIkgwLjVWXCIgKyByYW5nZTEgKyBcIkhcIiArIGsgKiB0aWNrU2l6ZU91dGVyXG4gICAgICAgICAgICA6IFwiTVwiICsgcmFuZ2UwICsgXCIsXCIgKyBrICogdGlja1NpemVPdXRlciArIFwiVjAuNUhcIiArIHJhbmdlMSArIFwiVlwiICsgayAqIHRpY2tTaXplT3V0ZXIpO1xuXG4gICAgdGlja1xuICAgICAgICAuYXR0cihcIm9wYWNpdHlcIiwgMSlcbiAgICAgICAgLmF0dHIoXCJ0cmFuc2Zvcm1cIiwgZnVuY3Rpb24oZCkgeyByZXR1cm4gdHJhbnNmb3JtKHBvc2l0aW9uKGQpKTsgfSk7XG5cbiAgICBsaW5lXG4gICAgICAgIC5hdHRyKHggKyBcIjJcIiwgayAqIHRpY2tTaXplSW5uZXIpO1xuXG4gICAgdGV4dFxuICAgICAgICAuYXR0cih4LCBrICogc3BhY2luZylcbiAgICAgICAgLnRleHQoZm9ybWF0KTtcblxuICAgIHNlbGVjdGlvbi5maWx0ZXIoZW50ZXJpbmcpXG4gICAgICAgIC5hdHRyKFwiZmlsbFwiLCBcIm5vbmVcIilcbiAgICAgICAgLmF0dHIoXCJmb250LXNpemVcIiwgMTApXG4gICAgICAgIC5hdHRyKFwiZm9udC1mYW1pbHlcIiwgXCJzYW5zLXNlcmlmXCIpXG4gICAgICAgIC5hdHRyKFwidGV4dC1hbmNob3JcIiwgb3JpZW50ID09PSByaWdodCA/IFwic3RhcnRcIiA6IG9yaWVudCA9PT0gbGVmdCA/IFwiZW5kXCIgOiBcIm1pZGRsZVwiKTtcblxuICAgIHNlbGVjdGlvblxuICAgICAgICAuZWFjaChmdW5jdGlvbigpIHsgdGhpcy5fX2F4aXMgPSBwb3NpdGlvbjsgfSk7XG4gIH1cblxuICBheGlzLnNjYWxlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNjYWxlID0gXywgYXhpcykgOiBzY2FsZTtcbiAgfTtcblxuICBheGlzLnRpY2tzID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRpY2tBcmd1bWVudHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cyksIGF4aXM7XG4gIH07XG5cbiAgYXhpcy50aWNrQXJndW1lbnRzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tBcmd1bWVudHMgPSBfID09IG51bGwgPyBbXSA6IHNsaWNlLmNhbGwoXyksIGF4aXMpIDogdGlja0FyZ3VtZW50cy5zbGljZSgpO1xuICB9O1xuXG4gIGF4aXMudGlja1ZhbHVlcyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrVmFsdWVzID0gXyA9PSBudWxsID8gbnVsbCA6IHNsaWNlLmNhbGwoXyksIGF4aXMpIDogdGlja1ZhbHVlcyAmJiB0aWNrVmFsdWVzLnNsaWNlKCk7XG4gIH07XG5cbiAgYXhpcy50aWNrRm9ybWF0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tGb3JtYXQgPSBfLCBheGlzKSA6IHRpY2tGb3JtYXQ7XG4gIH07XG5cbiAgYXhpcy50aWNrU2l6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrU2l6ZUlubmVyID0gdGlja1NpemVPdXRlciA9ICtfLCBheGlzKSA6IHRpY2tTaXplSW5uZXI7XG4gIH07XG5cbiAgYXhpcy50aWNrU2l6ZUlubmVyID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tTaXplSW5uZXIgPSArXywgYXhpcykgOiB0aWNrU2l6ZUlubmVyO1xuICB9O1xuXG4gIGF4aXMudGlja1NpemVPdXRlciA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aWNrU2l6ZU91dGVyID0gK18sIGF4aXMpIDogdGlja1NpemVPdXRlcjtcbiAgfTtcblxuICBheGlzLnRpY2tQYWRkaW5nID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRpY2tQYWRkaW5nID0gK18sIGF4aXMpIDogdGlja1BhZGRpbmc7XG4gIH07XG5cbiAgcmV0dXJuIGF4aXM7XG59XG5cbmZ1bmN0aW9uIGF4aXNUb3Aoc2NhbGUpIHtcbiAgcmV0dXJuIGF4aXModG9wLCBzY2FsZSk7XG59XG5cbmZ1bmN0aW9uIGF4aXNSaWdodChzY2FsZSkge1xuICByZXR1cm4gYXhpcyhyaWdodCwgc2NhbGUpO1xufVxuXG5mdW5jdGlvbiBheGlzQm90dG9tKHNjYWxlKSB7XG4gIHJldHVybiBheGlzKGJvdHRvbSwgc2NhbGUpO1xufVxuXG5mdW5jdGlvbiBheGlzTGVmdChzY2FsZSkge1xuICByZXR1cm4gYXhpcyhsZWZ0LCBzY2FsZSk7XG59XG5cbmV4cG9ydHMuYXhpc1RvcCA9IGF4aXNUb3A7XG5leHBvcnRzLmF4aXNSaWdodCA9IGF4aXNSaWdodDtcbmV4cG9ydHMuYXhpc0JvdHRvbSA9IGF4aXNCb3R0b207XG5leHBvcnRzLmF4aXNMZWZ0ID0gYXhpc0xlZnQ7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWJydXNoLyBWZXJzaW9uIDEuMC40LiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIHJlcXVpcmUoJ2QzLWRpc3BhdGNoJyksIHJlcXVpcmUoJ2QzLWRyYWcnKSwgcmVxdWlyZSgnZDMtaW50ZXJwb2xhdGUnKSwgcmVxdWlyZSgnZDMtc2VsZWN0aW9uJyksIHJlcXVpcmUoJ2QzLXRyYW5zaXRpb24nKSkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ2QzLWRpc3BhdGNoJywgJ2QzLWRyYWcnLCAnZDMtaW50ZXJwb2xhdGUnLCAnZDMtc2VsZWN0aW9uJywgJ2QzLXRyYW5zaXRpb24nXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cyxkM0Rpc3BhdGNoLGQzRHJhZyxkM0ludGVycG9sYXRlLGQzU2VsZWN0aW9uLGQzVHJhbnNpdGlvbikgeyAndXNlIHN0cmljdCc7XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxudmFyIEJydXNoRXZlbnQgPSBmdW5jdGlvbih0YXJnZXQsIHR5cGUsIHNlbGVjdGlvbikge1xuICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgdGhpcy50eXBlID0gdHlwZTtcbiAgdGhpcy5zZWxlY3Rpb24gPSBzZWxlY3Rpb247XG59O1xuXG5mdW5jdGlvbiBub3Byb3BhZ2F0aW9uKCkge1xuICBkM1NlbGVjdGlvbi5ldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbn1cblxudmFyIG5vZXZlbnQgPSBmdW5jdGlvbigpIHtcbiAgZDNTZWxlY3Rpb24uZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgZDNTZWxlY3Rpb24uZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG59O1xuXG52YXIgTU9ERV9EUkFHID0ge25hbWU6IFwiZHJhZ1wifTtcbnZhciBNT0RFX1NQQUNFID0ge25hbWU6IFwic3BhY2VcIn07XG52YXIgTU9ERV9IQU5ETEUgPSB7bmFtZTogXCJoYW5kbGVcIn07XG52YXIgTU9ERV9DRU5URVIgPSB7bmFtZTogXCJjZW50ZXJcIn07XG5cbnZhciBYID0ge1xuICBuYW1lOiBcInhcIixcbiAgaGFuZGxlczogW1wiZVwiLCBcIndcIl0ubWFwKHR5cGUpLFxuICBpbnB1dDogZnVuY3Rpb24oeCwgZSkgeyByZXR1cm4geCAmJiBbW3hbMF0sIGVbMF1bMV1dLCBbeFsxXSwgZVsxXVsxXV1dOyB9LFxuICBvdXRwdXQ6IGZ1bmN0aW9uKHh5KSB7IHJldHVybiB4eSAmJiBbeHlbMF1bMF0sIHh5WzFdWzBdXTsgfVxufTtcblxudmFyIFkgPSB7XG4gIG5hbWU6IFwieVwiLFxuICBoYW5kbGVzOiBbXCJuXCIsIFwic1wiXS5tYXAodHlwZSksXG4gIGlucHV0OiBmdW5jdGlvbih5LCBlKSB7IHJldHVybiB5ICYmIFtbZVswXVswXSwgeVswXV0sIFtlWzFdWzBdLCB5WzFdXV07IH0sXG4gIG91dHB1dDogZnVuY3Rpb24oeHkpIHsgcmV0dXJuIHh5ICYmIFt4eVswXVsxXSwgeHlbMV1bMV1dOyB9XG59O1xuXG52YXIgWFkgPSB7XG4gIG5hbWU6IFwieHlcIixcbiAgaGFuZGxlczogW1wiblwiLCBcImVcIiwgXCJzXCIsIFwid1wiLCBcIm53XCIsIFwibmVcIiwgXCJzZVwiLCBcInN3XCJdLm1hcCh0eXBlKSxcbiAgaW5wdXQ6IGZ1bmN0aW9uKHh5KSB7IHJldHVybiB4eTsgfSxcbiAgb3V0cHV0OiBmdW5jdGlvbih4eSkgeyByZXR1cm4geHk7IH1cbn07XG5cbnZhciBjdXJzb3JzID0ge1xuICBvdmVybGF5OiBcImNyb3NzaGFpclwiLFxuICBzZWxlY3Rpb246IFwibW92ZVwiLFxuICBuOiBcIm5zLXJlc2l6ZVwiLFxuICBlOiBcImV3LXJlc2l6ZVwiLFxuICBzOiBcIm5zLXJlc2l6ZVwiLFxuICB3OiBcImV3LXJlc2l6ZVwiLFxuICBudzogXCJud3NlLXJlc2l6ZVwiLFxuICBuZTogXCJuZXN3LXJlc2l6ZVwiLFxuICBzZTogXCJud3NlLXJlc2l6ZVwiLFxuICBzdzogXCJuZXN3LXJlc2l6ZVwiXG59O1xuXG52YXIgZmxpcFggPSB7XG4gIGU6IFwid1wiLFxuICB3OiBcImVcIixcbiAgbnc6IFwibmVcIixcbiAgbmU6IFwibndcIixcbiAgc2U6IFwic3dcIixcbiAgc3c6IFwic2VcIlxufTtcblxudmFyIGZsaXBZID0ge1xuICBuOiBcInNcIixcbiAgczogXCJuXCIsXG4gIG53OiBcInN3XCIsXG4gIG5lOiBcInNlXCIsXG4gIHNlOiBcIm5lXCIsXG4gIHN3OiBcIm53XCJcbn07XG5cbnZhciBzaWduc1ggPSB7XG4gIG92ZXJsYXk6ICsxLFxuICBzZWxlY3Rpb246ICsxLFxuICBuOiBudWxsLFxuICBlOiArMSxcbiAgczogbnVsbCxcbiAgdzogLTEsXG4gIG53OiAtMSxcbiAgbmU6ICsxLFxuICBzZTogKzEsXG4gIHN3OiAtMVxufTtcblxudmFyIHNpZ25zWSA9IHtcbiAgb3ZlcmxheTogKzEsXG4gIHNlbGVjdGlvbjogKzEsXG4gIG46IC0xLFxuICBlOiBudWxsLFxuICBzOiArMSxcbiAgdzogbnVsbCxcbiAgbnc6IC0xLFxuICBuZTogLTEsXG4gIHNlOiArMSxcbiAgc3c6ICsxXG59O1xuXG5mdW5jdGlvbiB0eXBlKHQpIHtcbiAgcmV0dXJuIHt0eXBlOiB0fTtcbn1cblxuLy8gSWdub3JlIHJpZ2h0LWNsaWNrLCBzaW5jZSB0aGF0IHNob3VsZCBvcGVuIHRoZSBjb250ZXh0IG1lbnUuXG5mdW5jdGlvbiBkZWZhdWx0RmlsdGVyKCkge1xuICByZXR1cm4gIWQzU2VsZWN0aW9uLmV2ZW50LmJ1dHRvbjtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdEV4dGVudCgpIHtcbiAgdmFyIHN2ZyA9IHRoaXMub3duZXJTVkdFbGVtZW50IHx8IHRoaXM7XG4gIHJldHVybiBbWzAsIDBdLCBbc3ZnLndpZHRoLmJhc2VWYWwudmFsdWUsIHN2Zy5oZWlnaHQuYmFzZVZhbC52YWx1ZV1dO1xufVxuXG4vLyBMaWtlIGQzLmxvY2FsLCBidXQgd2l0aCB0aGUgbmFtZSDigJxfX2JydXNo4oCdIHJhdGhlciB0aGFuIGF1dG8tZ2VuZXJhdGVkLlxuZnVuY3Rpb24gbG9jYWwobm9kZSkge1xuICB3aGlsZSAoIW5vZGUuX19icnVzaCkgaWYgKCEobm9kZSA9IG5vZGUucGFyZW50Tm9kZSkpIHJldHVybjtcbiAgcmV0dXJuIG5vZGUuX19icnVzaDtcbn1cblxuZnVuY3Rpb24gZW1wdHkoZXh0ZW50KSB7XG4gIHJldHVybiBleHRlbnRbMF1bMF0gPT09IGV4dGVudFsxXVswXVxuICAgICAgfHwgZXh0ZW50WzBdWzFdID09PSBleHRlbnRbMV1bMV07XG59XG5cbmZ1bmN0aW9uIGJydXNoU2VsZWN0aW9uKG5vZGUpIHtcbiAgdmFyIHN0YXRlID0gbm9kZS5fX2JydXNoO1xuICByZXR1cm4gc3RhdGUgPyBzdGF0ZS5kaW0ub3V0cHV0KHN0YXRlLnNlbGVjdGlvbikgOiBudWxsO1xufVxuXG5mdW5jdGlvbiBicnVzaFgoKSB7XG4gIHJldHVybiBicnVzaCQxKFgpO1xufVxuXG5mdW5jdGlvbiBicnVzaFkoKSB7XG4gIHJldHVybiBicnVzaCQxKFkpO1xufVxuXG52YXIgYnJ1c2ggPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIGJydXNoJDEoWFkpO1xufTtcblxuZnVuY3Rpb24gYnJ1c2gkMShkaW0pIHtcbiAgdmFyIGV4dGVudCA9IGRlZmF1bHRFeHRlbnQsXG4gICAgICBmaWx0ZXIgPSBkZWZhdWx0RmlsdGVyLFxuICAgICAgbGlzdGVuZXJzID0gZDNEaXNwYXRjaC5kaXNwYXRjaChicnVzaCwgXCJzdGFydFwiLCBcImJydXNoXCIsIFwiZW5kXCIpLFxuICAgICAgaGFuZGxlU2l6ZSA9IDYsXG4gICAgICB0b3VjaGVuZGluZztcblxuICBmdW5jdGlvbiBicnVzaChncm91cCkge1xuICAgIHZhciBvdmVybGF5ID0gZ3JvdXBcbiAgICAgICAgLnByb3BlcnR5KFwiX19icnVzaFwiLCBpbml0aWFsaXplKVxuICAgICAgLnNlbGVjdEFsbChcIi5vdmVybGF5XCIpXG4gICAgICAuZGF0YShbdHlwZShcIm92ZXJsYXlcIildKTtcblxuICAgIG92ZXJsYXkuZW50ZXIoKS5hcHBlbmQoXCJyZWN0XCIpXG4gICAgICAgIC5hdHRyKFwiY2xhc3NcIiwgXCJvdmVybGF5XCIpXG4gICAgICAgIC5hdHRyKFwicG9pbnRlci1ldmVudHNcIiwgXCJhbGxcIilcbiAgICAgICAgLmF0dHIoXCJjdXJzb3JcIiwgY3Vyc29ycy5vdmVybGF5KVxuICAgICAgLm1lcmdlKG92ZXJsYXkpXG4gICAgICAgIC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciBleHRlbnQgPSBsb2NhbCh0aGlzKS5leHRlbnQ7XG4gICAgICAgICAgZDNTZWxlY3Rpb24uc2VsZWN0KHRoaXMpXG4gICAgICAgICAgICAgIC5hdHRyKFwieFwiLCBleHRlbnRbMF1bMF0pXG4gICAgICAgICAgICAgIC5hdHRyKFwieVwiLCBleHRlbnRbMF1bMV0pXG4gICAgICAgICAgICAgIC5hdHRyKFwid2lkdGhcIiwgZXh0ZW50WzFdWzBdIC0gZXh0ZW50WzBdWzBdKVxuICAgICAgICAgICAgICAuYXR0cihcImhlaWdodFwiLCBleHRlbnRbMV1bMV0gLSBleHRlbnRbMF1bMV0pO1xuICAgICAgICB9KTtcblxuICAgIGdyb3VwLnNlbGVjdEFsbChcIi5zZWxlY3Rpb25cIilcbiAgICAgIC5kYXRhKFt0eXBlKFwic2VsZWN0aW9uXCIpXSlcbiAgICAgIC5lbnRlcigpLmFwcGVuZChcInJlY3RcIilcbiAgICAgICAgLmF0dHIoXCJjbGFzc1wiLCBcInNlbGVjdGlvblwiKVxuICAgICAgICAuYXR0cihcImN1cnNvclwiLCBjdXJzb3JzLnNlbGVjdGlvbilcbiAgICAgICAgLmF0dHIoXCJmaWxsXCIsIFwiIzc3N1wiKVxuICAgICAgICAuYXR0cihcImZpbGwtb3BhY2l0eVwiLCAwLjMpXG4gICAgICAgIC5hdHRyKFwic3Ryb2tlXCIsIFwiI2ZmZlwiKVxuICAgICAgICAuYXR0cihcInNoYXBlLXJlbmRlcmluZ1wiLCBcImNyaXNwRWRnZXNcIik7XG5cbiAgICB2YXIgaGFuZGxlID0gZ3JvdXAuc2VsZWN0QWxsKFwiLmhhbmRsZVwiKVxuICAgICAgLmRhdGEoZGltLmhhbmRsZXMsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQudHlwZTsgfSk7XG5cbiAgICBoYW5kbGUuZXhpdCgpLnJlbW92ZSgpO1xuXG4gICAgaGFuZGxlLmVudGVyKCkuYXBwZW5kKFwicmVjdFwiKVxuICAgICAgICAuYXR0cihcImNsYXNzXCIsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIFwiaGFuZGxlIGhhbmRsZS0tXCIgKyBkLnR5cGU7IH0pXG4gICAgICAgIC5hdHRyKFwiY3Vyc29yXCIsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGN1cnNvcnNbZC50eXBlXTsgfSk7XG5cbiAgICBncm91cFxuICAgICAgICAuZWFjaChyZWRyYXcpXG4gICAgICAgIC5hdHRyKFwiZmlsbFwiLCBcIm5vbmVcIilcbiAgICAgICAgLmF0dHIoXCJwb2ludGVyLWV2ZW50c1wiLCBcImFsbFwiKVxuICAgICAgICAuc3R5bGUoXCItd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3JcIiwgXCJyZ2JhKDAsMCwwLDApXCIpXG4gICAgICAgIC5vbihcIm1vdXNlZG93bi5icnVzaCB0b3VjaHN0YXJ0LmJydXNoXCIsIHN0YXJ0ZWQpO1xuICB9XG5cbiAgYnJ1c2gubW92ZSA9IGZ1bmN0aW9uKGdyb3VwLCBzZWxlY3Rpb24pIHtcbiAgICBpZiAoZ3JvdXAuc2VsZWN0aW9uKSB7XG4gICAgICBncm91cFxuICAgICAgICAgIC5vbihcInN0YXJ0LmJydXNoXCIsIGZ1bmN0aW9uKCkgeyBlbWl0dGVyKHRoaXMsIGFyZ3VtZW50cykuYmVmb3Jlc3RhcnQoKS5zdGFydCgpOyB9KVxuICAgICAgICAgIC5vbihcImludGVycnVwdC5icnVzaCBlbmQuYnJ1c2hcIiwgZnVuY3Rpb24oKSB7IGVtaXR0ZXIodGhpcywgYXJndW1lbnRzKS5lbmQoKTsgfSlcbiAgICAgICAgICAudHdlZW4oXCJicnVzaFwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcyxcbiAgICAgICAgICAgICAgICBzdGF0ZSA9IHRoYXQuX19icnVzaCxcbiAgICAgICAgICAgICAgICBlbWl0ID0gZW1pdHRlcih0aGF0LCBhcmd1bWVudHMpLFxuICAgICAgICAgICAgICAgIHNlbGVjdGlvbjAgPSBzdGF0ZS5zZWxlY3Rpb24sXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uMSA9IGRpbS5pbnB1dCh0eXBlb2Ygc2VsZWN0aW9uID09PSBcImZ1bmN0aW9uXCIgPyBzZWxlY3Rpb24uYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IHNlbGVjdGlvbiwgc3RhdGUuZXh0ZW50KSxcbiAgICAgICAgICAgICAgICBpID0gZDNJbnRlcnBvbGF0ZS5pbnRlcnBvbGF0ZShzZWxlY3Rpb24wLCBzZWxlY3Rpb24xKTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdHdlZW4odCkge1xuICAgICAgICAgICAgICBzdGF0ZS5zZWxlY3Rpb24gPSB0ID09PSAxICYmIGVtcHR5KHNlbGVjdGlvbjEpID8gbnVsbCA6IGkodCk7XG4gICAgICAgICAgICAgIHJlZHJhdy5jYWxsKHRoYXQpO1xuICAgICAgICAgICAgICBlbWl0LmJydXNoKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBzZWxlY3Rpb24wICYmIHNlbGVjdGlvbjEgPyB0d2VlbiA6IHR3ZWVuKDEpO1xuICAgICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBncm91cFxuICAgICAgICAgIC5lYWNoKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLFxuICAgICAgICAgICAgICAgIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgICAgICAgc3RhdGUgPSB0aGF0Ll9fYnJ1c2gsXG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uMSA9IGRpbS5pbnB1dCh0eXBlb2Ygc2VsZWN0aW9uID09PSBcImZ1bmN0aW9uXCIgPyBzZWxlY3Rpb24uYXBwbHkodGhhdCwgYXJncykgOiBzZWxlY3Rpb24sIHN0YXRlLmV4dGVudCksXG4gICAgICAgICAgICAgICAgZW1pdCA9IGVtaXR0ZXIodGhhdCwgYXJncykuYmVmb3Jlc3RhcnQoKTtcblxuICAgICAgICAgICAgZDNUcmFuc2l0aW9uLmludGVycnVwdCh0aGF0KTtcbiAgICAgICAgICAgIHN0YXRlLnNlbGVjdGlvbiA9IHNlbGVjdGlvbjEgPT0gbnVsbCB8fCBlbXB0eShzZWxlY3Rpb24xKSA/IG51bGwgOiBzZWxlY3Rpb24xO1xuICAgICAgICAgICAgcmVkcmF3LmNhbGwodGhhdCk7XG4gICAgICAgICAgICBlbWl0LnN0YXJ0KCkuYnJ1c2goKS5lbmQoKTtcbiAgICAgICAgICB9KTtcbiAgICB9XG4gIH07XG5cbiAgZnVuY3Rpb24gcmVkcmF3KCkge1xuICAgIHZhciBncm91cCA9IGQzU2VsZWN0aW9uLnNlbGVjdCh0aGlzKSxcbiAgICAgICAgc2VsZWN0aW9uID0gbG9jYWwodGhpcykuc2VsZWN0aW9uO1xuXG4gICAgaWYgKHNlbGVjdGlvbikge1xuICAgICAgZ3JvdXAuc2VsZWN0QWxsKFwiLnNlbGVjdGlvblwiKVxuICAgICAgICAgIC5zdHlsZShcImRpc3BsYXlcIiwgbnVsbClcbiAgICAgICAgICAuYXR0cihcInhcIiwgc2VsZWN0aW9uWzBdWzBdKVxuICAgICAgICAgIC5hdHRyKFwieVwiLCBzZWxlY3Rpb25bMF1bMV0pXG4gICAgICAgICAgLmF0dHIoXCJ3aWR0aFwiLCBzZWxlY3Rpb25bMV1bMF0gLSBzZWxlY3Rpb25bMF1bMF0pXG4gICAgICAgICAgLmF0dHIoXCJoZWlnaHRcIiwgc2VsZWN0aW9uWzFdWzFdIC0gc2VsZWN0aW9uWzBdWzFdKTtcblxuICAgICAgZ3JvdXAuc2VsZWN0QWxsKFwiLmhhbmRsZVwiKVxuICAgICAgICAgIC5zdHlsZShcImRpc3BsYXlcIiwgbnVsbClcbiAgICAgICAgICAuYXR0cihcInhcIiwgZnVuY3Rpb24oZCkgeyByZXR1cm4gZC50eXBlW2QudHlwZS5sZW5ndGggLSAxXSA9PT0gXCJlXCIgPyBzZWxlY3Rpb25bMV1bMF0gLSBoYW5kbGVTaXplIC8gMiA6IHNlbGVjdGlvblswXVswXSAtIGhhbmRsZVNpemUgLyAyOyB9KVxuICAgICAgICAgIC5hdHRyKFwieVwiLCBmdW5jdGlvbihkKSB7IHJldHVybiBkLnR5cGVbMF0gPT09IFwic1wiID8gc2VsZWN0aW9uWzFdWzFdIC0gaGFuZGxlU2l6ZSAvIDIgOiBzZWxlY3Rpb25bMF1bMV0gLSBoYW5kbGVTaXplIC8gMjsgfSlcbiAgICAgICAgICAuYXR0cihcIndpZHRoXCIsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQudHlwZSA9PT0gXCJuXCIgfHwgZC50eXBlID09PSBcInNcIiA/IHNlbGVjdGlvblsxXVswXSAtIHNlbGVjdGlvblswXVswXSArIGhhbmRsZVNpemUgOiBoYW5kbGVTaXplOyB9KVxuICAgICAgICAgIC5hdHRyKFwiaGVpZ2h0XCIsIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGQudHlwZSA9PT0gXCJlXCIgfHwgZC50eXBlID09PSBcIndcIiA/IHNlbGVjdGlvblsxXVsxXSAtIHNlbGVjdGlvblswXVsxXSArIGhhbmRsZVNpemUgOiBoYW5kbGVTaXplOyB9KTtcbiAgICB9XG5cbiAgICBlbHNlIHtcbiAgICAgIGdyb3VwLnNlbGVjdEFsbChcIi5zZWxlY3Rpb24sLmhhbmRsZVwiKVxuICAgICAgICAgIC5zdHlsZShcImRpc3BsYXlcIiwgXCJub25lXCIpXG4gICAgICAgICAgLmF0dHIoXCJ4XCIsIG51bGwpXG4gICAgICAgICAgLmF0dHIoXCJ5XCIsIG51bGwpXG4gICAgICAgICAgLmF0dHIoXCJ3aWR0aFwiLCBudWxsKVxuICAgICAgICAgIC5hdHRyKFwiaGVpZ2h0XCIsIG51bGwpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGVtaXR0ZXIodGhhdCwgYXJncykge1xuICAgIHJldHVybiB0aGF0Ll9fYnJ1c2guZW1pdHRlciB8fCBuZXcgRW1pdHRlcih0aGF0LCBhcmdzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEVtaXR0ZXIodGhhdCwgYXJncykge1xuICAgIHRoaXMudGhhdCA9IHRoYXQ7XG4gICAgdGhpcy5hcmdzID0gYXJncztcbiAgICB0aGlzLnN0YXRlID0gdGhhdC5fX2JydXNoO1xuICAgIHRoaXMuYWN0aXZlID0gMDtcbiAgfVxuXG4gIEVtaXR0ZXIucHJvdG90eXBlID0ge1xuICAgIGJlZm9yZXN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICgrK3RoaXMuYWN0aXZlID09PSAxKSB0aGlzLnN0YXRlLmVtaXR0ZXIgPSB0aGlzLCB0aGlzLnN0YXJ0aW5nID0gdHJ1ZTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgc3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHRoaXMuc3RhcnRpbmcpIHRoaXMuc3RhcnRpbmcgPSBmYWxzZSwgdGhpcy5lbWl0KFwic3RhcnRcIik7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIGJydXNoOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuZW1pdChcImJydXNoXCIpO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBlbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKC0tdGhpcy5hY3RpdmUgPT09IDApIGRlbGV0ZSB0aGlzLnN0YXRlLmVtaXR0ZXIsIHRoaXMuZW1pdChcImVuZFwiKTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgZW1pdDogZnVuY3Rpb24odHlwZSkge1xuICAgICAgZDNTZWxlY3Rpb24uY3VzdG9tRXZlbnQobmV3IEJydXNoRXZlbnQoYnJ1c2gsIHR5cGUsIGRpbS5vdXRwdXQodGhpcy5zdGF0ZS5zZWxlY3Rpb24pKSwgbGlzdGVuZXJzLmFwcGx5LCBsaXN0ZW5lcnMsIFt0eXBlLCB0aGlzLnRoYXQsIHRoaXMuYXJnc10pO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBzdGFydGVkKCkge1xuICAgIGlmIChkM1NlbGVjdGlvbi5ldmVudC50b3VjaGVzKSB7IGlmIChkM1NlbGVjdGlvbi5ldmVudC5jaGFuZ2VkVG91Y2hlcy5sZW5ndGggPCBkM1NlbGVjdGlvbi5ldmVudC50b3VjaGVzLmxlbmd0aCkgcmV0dXJuIG5vZXZlbnQoKTsgfVxuICAgIGVsc2UgaWYgKHRvdWNoZW5kaW5nKSByZXR1cm47XG4gICAgaWYgKCFmaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSkgcmV0dXJuO1xuXG4gICAgdmFyIHRoYXQgPSB0aGlzLFxuICAgICAgICB0eXBlID0gZDNTZWxlY3Rpb24uZXZlbnQudGFyZ2V0Ll9fZGF0YV9fLnR5cGUsXG4gICAgICAgIG1vZGUgPSAoZDNTZWxlY3Rpb24uZXZlbnQubWV0YUtleSA/IHR5cGUgPSBcIm92ZXJsYXlcIiA6IHR5cGUpID09PSBcInNlbGVjdGlvblwiID8gTU9ERV9EUkFHIDogKGQzU2VsZWN0aW9uLmV2ZW50LmFsdEtleSA/IE1PREVfQ0VOVEVSIDogTU9ERV9IQU5ETEUpLFxuICAgICAgICBzaWduWCA9IGRpbSA9PT0gWSA/IG51bGwgOiBzaWduc1hbdHlwZV0sXG4gICAgICAgIHNpZ25ZID0gZGltID09PSBYID8gbnVsbCA6IHNpZ25zWVt0eXBlXSxcbiAgICAgICAgc3RhdGUgPSBsb2NhbCh0aGF0KSxcbiAgICAgICAgZXh0ZW50ID0gc3RhdGUuZXh0ZW50LFxuICAgICAgICBzZWxlY3Rpb24gPSBzdGF0ZS5zZWxlY3Rpb24sXG4gICAgICAgIFcgPSBleHRlbnRbMF1bMF0sIHcwLCB3MSxcbiAgICAgICAgTiA9IGV4dGVudFswXVsxXSwgbjAsIG4xLFxuICAgICAgICBFID0gZXh0ZW50WzFdWzBdLCBlMCwgZTEsXG4gICAgICAgIFMgPSBleHRlbnRbMV1bMV0sIHMwLCBzMSxcbiAgICAgICAgZHgsXG4gICAgICAgIGR5LFxuICAgICAgICBtb3ZpbmcsXG4gICAgICAgIHNoaWZ0aW5nID0gc2lnblggJiYgc2lnblkgJiYgZDNTZWxlY3Rpb24uZXZlbnQuc2hpZnRLZXksXG4gICAgICAgIGxvY2tYLFxuICAgICAgICBsb2NrWSxcbiAgICAgICAgcG9pbnQwID0gZDNTZWxlY3Rpb24ubW91c2UodGhhdCksXG4gICAgICAgIHBvaW50ID0gcG9pbnQwLFxuICAgICAgICBlbWl0ID0gZW1pdHRlcih0aGF0LCBhcmd1bWVudHMpLmJlZm9yZXN0YXJ0KCk7XG5cbiAgICBpZiAodHlwZSA9PT0gXCJvdmVybGF5XCIpIHtcbiAgICAgIHN0YXRlLnNlbGVjdGlvbiA9IHNlbGVjdGlvbiA9IFtcbiAgICAgICAgW3cwID0gZGltID09PSBZID8gVyA6IHBvaW50MFswXSwgbjAgPSBkaW0gPT09IFggPyBOIDogcG9pbnQwWzFdXSxcbiAgICAgICAgW2UwID0gZGltID09PSBZID8gRSA6IHcwLCBzMCA9IGRpbSA9PT0gWCA/IFMgOiBuMF1cbiAgICAgIF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHcwID0gc2VsZWN0aW9uWzBdWzBdO1xuICAgICAgbjAgPSBzZWxlY3Rpb25bMF1bMV07XG4gICAgICBlMCA9IHNlbGVjdGlvblsxXVswXTtcbiAgICAgIHMwID0gc2VsZWN0aW9uWzFdWzFdO1xuICAgIH1cblxuICAgIHcxID0gdzA7XG4gICAgbjEgPSBuMDtcbiAgICBlMSA9IGUwO1xuICAgIHMxID0gczA7XG5cbiAgICB2YXIgZ3JvdXAgPSBkM1NlbGVjdGlvbi5zZWxlY3QodGhhdClcbiAgICAgICAgLmF0dHIoXCJwb2ludGVyLWV2ZW50c1wiLCBcIm5vbmVcIik7XG5cbiAgICB2YXIgb3ZlcmxheSA9IGdyb3VwLnNlbGVjdEFsbChcIi5vdmVybGF5XCIpXG4gICAgICAgIC5hdHRyKFwiY3Vyc29yXCIsIGN1cnNvcnNbdHlwZV0pO1xuXG4gICAgaWYgKGQzU2VsZWN0aW9uLmV2ZW50LnRvdWNoZXMpIHtcbiAgICAgIGdyb3VwXG4gICAgICAgICAgLm9uKFwidG91Y2htb3ZlLmJydXNoXCIsIG1vdmVkLCB0cnVlKVxuICAgICAgICAgIC5vbihcInRvdWNoZW5kLmJydXNoIHRvdWNoY2FuY2VsLmJydXNoXCIsIGVuZGVkLCB0cnVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHZpZXcgPSBkM1NlbGVjdGlvbi5zZWxlY3QoZDNTZWxlY3Rpb24uZXZlbnQudmlldylcbiAgICAgICAgICAub24oXCJrZXlkb3duLmJydXNoXCIsIGtleWRvd25lZCwgdHJ1ZSlcbiAgICAgICAgICAub24oXCJrZXl1cC5icnVzaFwiLCBrZXl1cHBlZCwgdHJ1ZSlcbiAgICAgICAgICAub24oXCJtb3VzZW1vdmUuYnJ1c2hcIiwgbW92ZWQsIHRydWUpXG4gICAgICAgICAgLm9uKFwibW91c2V1cC5icnVzaFwiLCBlbmRlZCwgdHJ1ZSk7XG5cbiAgICAgIGQzRHJhZy5kcmFnRGlzYWJsZShkM1NlbGVjdGlvbi5ldmVudC52aWV3KTtcbiAgICB9XG5cbiAgICBub3Byb3BhZ2F0aW9uKCk7XG4gICAgZDNUcmFuc2l0aW9uLmludGVycnVwdCh0aGF0KTtcbiAgICByZWRyYXcuY2FsbCh0aGF0KTtcbiAgICBlbWl0LnN0YXJ0KCk7XG5cbiAgICBmdW5jdGlvbiBtb3ZlZCgpIHtcbiAgICAgIHZhciBwb2ludDEgPSBkM1NlbGVjdGlvbi5tb3VzZSh0aGF0KTtcbiAgICAgIGlmIChzaGlmdGluZyAmJiAhbG9ja1ggJiYgIWxvY2tZKSB7XG4gICAgICAgIGlmIChNYXRoLmFicyhwb2ludDFbMF0gLSBwb2ludFswXSkgPiBNYXRoLmFicyhwb2ludDFbMV0gLSBwb2ludFsxXSkpIGxvY2tZID0gdHJ1ZTtcbiAgICAgICAgZWxzZSBsb2NrWCA9IHRydWU7XG4gICAgICB9XG4gICAgICBwb2ludCA9IHBvaW50MTtcbiAgICAgIG1vdmluZyA9IHRydWU7XG4gICAgICBub2V2ZW50KCk7XG4gICAgICBtb3ZlKCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbW92ZSgpIHtcbiAgICAgIHZhciB0O1xuXG4gICAgICBkeCA9IHBvaW50WzBdIC0gcG9pbnQwWzBdO1xuICAgICAgZHkgPSBwb2ludFsxXSAtIHBvaW50MFsxXTtcblxuICAgICAgc3dpdGNoIChtb2RlKSB7XG4gICAgICAgIGNhc2UgTU9ERV9TUEFDRTpcbiAgICAgICAgY2FzZSBNT0RFX0RSQUc6IHtcbiAgICAgICAgICBpZiAoc2lnblgpIGR4ID0gTWF0aC5tYXgoVyAtIHcwLCBNYXRoLm1pbihFIC0gZTAsIGR4KSksIHcxID0gdzAgKyBkeCwgZTEgPSBlMCArIGR4O1xuICAgICAgICAgIGlmIChzaWduWSkgZHkgPSBNYXRoLm1heChOIC0gbjAsIE1hdGgubWluKFMgLSBzMCwgZHkpKSwgbjEgPSBuMCArIGR5LCBzMSA9IHMwICsgZHk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBNT0RFX0hBTkRMRToge1xuICAgICAgICAgIGlmIChzaWduWCA8IDApIGR4ID0gTWF0aC5tYXgoVyAtIHcwLCBNYXRoLm1pbihFIC0gdzAsIGR4KSksIHcxID0gdzAgKyBkeCwgZTEgPSBlMDtcbiAgICAgICAgICBlbHNlIGlmIChzaWduWCA+IDApIGR4ID0gTWF0aC5tYXgoVyAtIGUwLCBNYXRoLm1pbihFIC0gZTAsIGR4KSksIHcxID0gdzAsIGUxID0gZTAgKyBkeDtcbiAgICAgICAgICBpZiAoc2lnblkgPCAwKSBkeSA9IE1hdGgubWF4KE4gLSBuMCwgTWF0aC5taW4oUyAtIG4wLCBkeSkpLCBuMSA9IG4wICsgZHksIHMxID0gczA7XG4gICAgICAgICAgZWxzZSBpZiAoc2lnblkgPiAwKSBkeSA9IE1hdGgubWF4KE4gLSBzMCwgTWF0aC5taW4oUyAtIHMwLCBkeSkpLCBuMSA9IG4wLCBzMSA9IHMwICsgZHk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSBNT0RFX0NFTlRFUjoge1xuICAgICAgICAgIGlmIChzaWduWCkgdzEgPSBNYXRoLm1heChXLCBNYXRoLm1pbihFLCB3MCAtIGR4ICogc2lnblgpKSwgZTEgPSBNYXRoLm1heChXLCBNYXRoLm1pbihFLCBlMCArIGR4ICogc2lnblgpKTtcbiAgICAgICAgICBpZiAoc2lnblkpIG4xID0gTWF0aC5tYXgoTiwgTWF0aC5taW4oUywgbjAgLSBkeSAqIHNpZ25ZKSksIHMxID0gTWF0aC5tYXgoTiwgTWF0aC5taW4oUywgczAgKyBkeSAqIHNpZ25ZKSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGUxIDwgdzEpIHtcbiAgICAgICAgc2lnblggKj0gLTE7XG4gICAgICAgIHQgPSB3MCwgdzAgPSBlMCwgZTAgPSB0O1xuICAgICAgICB0ID0gdzEsIHcxID0gZTEsIGUxID0gdDtcbiAgICAgICAgaWYgKHR5cGUgaW4gZmxpcFgpIG92ZXJsYXkuYXR0cihcImN1cnNvclwiLCBjdXJzb3JzW3R5cGUgPSBmbGlwWFt0eXBlXV0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoczEgPCBuMSkge1xuICAgICAgICBzaWduWSAqPSAtMTtcbiAgICAgICAgdCA9IG4wLCBuMCA9IHMwLCBzMCA9IHQ7XG4gICAgICAgIHQgPSBuMSwgbjEgPSBzMSwgczEgPSB0O1xuICAgICAgICBpZiAodHlwZSBpbiBmbGlwWSkgb3ZlcmxheS5hdHRyKFwiY3Vyc29yXCIsIGN1cnNvcnNbdHlwZSA9IGZsaXBZW3R5cGVdXSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzdGF0ZS5zZWxlY3Rpb24pIHNlbGVjdGlvbiA9IHN0YXRlLnNlbGVjdGlvbjsgLy8gTWF5IGJlIHNldCBieSBicnVzaC5tb3ZlIVxuICAgICAgaWYgKGxvY2tYKSB3MSA9IHNlbGVjdGlvblswXVswXSwgZTEgPSBzZWxlY3Rpb25bMV1bMF07XG4gICAgICBpZiAobG9ja1kpIG4xID0gc2VsZWN0aW9uWzBdWzFdLCBzMSA9IHNlbGVjdGlvblsxXVsxXTtcblxuICAgICAgaWYgKHNlbGVjdGlvblswXVswXSAhPT0gdzFcbiAgICAgICAgICB8fCBzZWxlY3Rpb25bMF1bMV0gIT09IG4xXG4gICAgICAgICAgfHwgc2VsZWN0aW9uWzFdWzBdICE9PSBlMVxuICAgICAgICAgIHx8IHNlbGVjdGlvblsxXVsxXSAhPT0gczEpIHtcbiAgICAgICAgc3RhdGUuc2VsZWN0aW9uID0gW1t3MSwgbjFdLCBbZTEsIHMxXV07XG4gICAgICAgIHJlZHJhdy5jYWxsKHRoYXQpO1xuICAgICAgICBlbWl0LmJydXNoKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW5kZWQoKSB7XG4gICAgICBub3Byb3BhZ2F0aW9uKCk7XG4gICAgICBpZiAoZDNTZWxlY3Rpb24uZXZlbnQudG91Y2hlcykge1xuICAgICAgICBpZiAoZDNTZWxlY3Rpb24uZXZlbnQudG91Y2hlcy5sZW5ndGgpIHJldHVybjtcbiAgICAgICAgaWYgKHRvdWNoZW5kaW5nKSBjbGVhclRpbWVvdXQodG91Y2hlbmRpbmcpO1xuICAgICAgICB0b3VjaGVuZGluZyA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IHRvdWNoZW5kaW5nID0gbnVsbDsgfSwgNTAwKTsgLy8gR2hvc3QgY2xpY2tzIGFyZSBkZWxheWVkIVxuICAgICAgICBncm91cC5vbihcInRvdWNobW92ZS5icnVzaCB0b3VjaGVuZC5icnVzaCB0b3VjaGNhbmNlbC5icnVzaFwiLCBudWxsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGQzRHJhZy5kcmFnRW5hYmxlKGQzU2VsZWN0aW9uLmV2ZW50LnZpZXcsIG1vdmluZyk7XG4gICAgICAgIHZpZXcub24oXCJrZXlkb3duLmJydXNoIGtleXVwLmJydXNoIG1vdXNlbW92ZS5icnVzaCBtb3VzZXVwLmJydXNoXCIsIG51bGwpO1xuICAgICAgfVxuICAgICAgZ3JvdXAuYXR0cihcInBvaW50ZXItZXZlbnRzXCIsIFwiYWxsXCIpO1xuICAgICAgb3ZlcmxheS5hdHRyKFwiY3Vyc29yXCIsIGN1cnNvcnMub3ZlcmxheSk7XG4gICAgICBpZiAoc3RhdGUuc2VsZWN0aW9uKSBzZWxlY3Rpb24gPSBzdGF0ZS5zZWxlY3Rpb247IC8vIE1heSBiZSBzZXQgYnkgYnJ1c2gubW92ZSAob24gc3RhcnQpIVxuICAgICAgaWYgKGVtcHR5KHNlbGVjdGlvbikpIHN0YXRlLnNlbGVjdGlvbiA9IG51bGwsIHJlZHJhdy5jYWxsKHRoYXQpO1xuICAgICAgZW1pdC5lbmQoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBrZXlkb3duZWQoKSB7XG4gICAgICBzd2l0Y2ggKGQzU2VsZWN0aW9uLmV2ZW50LmtleUNvZGUpIHtcbiAgICAgICAgY2FzZSAxNjogeyAvLyBTSElGVFxuICAgICAgICAgIHNoaWZ0aW5nID0gc2lnblggJiYgc2lnblk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgY2FzZSAxODogeyAvLyBBTFRcbiAgICAgICAgICBpZiAobW9kZSA9PT0gTU9ERV9IQU5ETEUpIHtcbiAgICAgICAgICAgIGlmIChzaWduWCkgZTAgPSBlMSAtIGR4ICogc2lnblgsIHcwID0gdzEgKyBkeCAqIHNpZ25YO1xuICAgICAgICAgICAgaWYgKHNpZ25ZKSBzMCA9IHMxIC0gZHkgKiBzaWduWSwgbjAgPSBuMSArIGR5ICogc2lnblk7XG4gICAgICAgICAgICBtb2RlID0gTU9ERV9DRU5URVI7XG4gICAgICAgICAgICBtb3ZlKCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGNhc2UgMzI6IHsgLy8gU1BBQ0U7IHRha2VzIHByaW9yaXR5IG92ZXIgQUxUXG4gICAgICAgICAgaWYgKG1vZGUgPT09IE1PREVfSEFORExFIHx8IG1vZGUgPT09IE1PREVfQ0VOVEVSKSB7XG4gICAgICAgICAgICBpZiAoc2lnblggPCAwKSBlMCA9IGUxIC0gZHg7IGVsc2UgaWYgKHNpZ25YID4gMCkgdzAgPSB3MSAtIGR4O1xuICAgICAgICAgICAgaWYgKHNpZ25ZIDwgMCkgczAgPSBzMSAtIGR5OyBlbHNlIGlmIChzaWduWSA+IDApIG4wID0gbjEgLSBkeTtcbiAgICAgICAgICAgIG1vZGUgPSBNT0RFX1NQQUNFO1xuICAgICAgICAgICAgb3ZlcmxheS5hdHRyKFwiY3Vyc29yXCIsIGN1cnNvcnMuc2VsZWN0aW9uKTtcbiAgICAgICAgICAgIG1vdmUoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDogcmV0dXJuO1xuICAgICAgfVxuICAgICAgbm9ldmVudCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGtleXVwcGVkKCkge1xuICAgICAgc3dpdGNoIChkM1NlbGVjdGlvbi5ldmVudC5rZXlDb2RlKSB7XG4gICAgICAgIGNhc2UgMTY6IHsgLy8gU0hJRlRcbiAgICAgICAgICBpZiAoc2hpZnRpbmcpIHtcbiAgICAgICAgICAgIGxvY2tYID0gbG9ja1kgPSBzaGlmdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgbW92ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDE4OiB7IC8vIEFMVFxuICAgICAgICAgIGlmIChtb2RlID09PSBNT0RFX0NFTlRFUikge1xuICAgICAgICAgICAgaWYgKHNpZ25YIDwgMCkgZTAgPSBlMTsgZWxzZSBpZiAoc2lnblggPiAwKSB3MCA9IHcxO1xuICAgICAgICAgICAgaWYgKHNpZ25ZIDwgMCkgczAgPSBzMTsgZWxzZSBpZiAoc2lnblkgPiAwKSBuMCA9IG4xO1xuICAgICAgICAgICAgbW9kZSA9IE1PREVfSEFORExFO1xuICAgICAgICAgICAgbW92ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBjYXNlIDMyOiB7IC8vIFNQQUNFXG4gICAgICAgICAgaWYgKG1vZGUgPT09IE1PREVfU1BBQ0UpIHtcbiAgICAgICAgICAgIGlmIChkM1NlbGVjdGlvbi5ldmVudC5hbHRLZXkpIHtcbiAgICAgICAgICAgICAgaWYgKHNpZ25YKSBlMCA9IGUxIC0gZHggKiBzaWduWCwgdzAgPSB3MSArIGR4ICogc2lnblg7XG4gICAgICAgICAgICAgIGlmIChzaWduWSkgczAgPSBzMSAtIGR5ICogc2lnblksIG4wID0gbjEgKyBkeSAqIHNpZ25ZO1xuICAgICAgICAgICAgICBtb2RlID0gTU9ERV9DRU5URVI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBpZiAoc2lnblggPCAwKSBlMCA9IGUxOyBlbHNlIGlmIChzaWduWCA+IDApIHcwID0gdzE7XG4gICAgICAgICAgICAgIGlmIChzaWduWSA8IDApIHMwID0gczE7IGVsc2UgaWYgKHNpZ25ZID4gMCkgbjAgPSBuMTtcbiAgICAgICAgICAgICAgbW9kZSA9IE1PREVfSEFORExFO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3ZlcmxheS5hdHRyKFwiY3Vyc29yXCIsIGN1cnNvcnNbdHlwZV0pO1xuICAgICAgICAgICAgbW92ZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICBkZWZhdWx0OiByZXR1cm47XG4gICAgICB9XG4gICAgICBub2V2ZW50KCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICB2YXIgc3RhdGUgPSB0aGlzLl9fYnJ1c2ggfHwge3NlbGVjdGlvbjogbnVsbH07XG4gICAgc3RhdGUuZXh0ZW50ID0gZXh0ZW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgc3RhdGUuZGltID0gZGltO1xuICAgIHJldHVybiBzdGF0ZTtcbiAgfVxuXG4gIGJydXNoLmV4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChleHRlbnQgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KFtbK19bMF1bMF0sICtfWzBdWzFdXSwgWytfWzFdWzBdLCArX1sxXVsxXV1dKSwgYnJ1c2gpIDogZXh0ZW50O1xuICB9O1xuXG4gIGJydXNoLmZpbHRlciA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChmaWx0ZXIgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCEhXyksIGJydXNoKSA6IGZpbHRlcjtcbiAgfTtcblxuICBicnVzaC5oYW5kbGVTaXplID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGhhbmRsZVNpemUgPSArXywgYnJ1c2gpIDogaGFuZGxlU2l6ZTtcbiAgfTtcblxuICBicnVzaC5vbiA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB2YWx1ZSA9IGxpc3RlbmVycy5vbi5hcHBseShsaXN0ZW5lcnMsIGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIHZhbHVlID09PSBsaXN0ZW5lcnMgPyBicnVzaCA6IHZhbHVlO1xuICB9O1xuXG4gIHJldHVybiBicnVzaDtcbn1cblxuZXhwb3J0cy5icnVzaCA9IGJydXNoO1xuZXhwb3J0cy5icnVzaFggPSBicnVzaFg7XG5leHBvcnRzLmJydXNoWSA9IGJydXNoWTtcbmV4cG9ydHMuYnJ1c2hTZWxlY3Rpb24gPSBicnVzaFNlbGVjdGlvbjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtY2hvcmQvIFZlcnNpb24gMS4wLjQuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgcmVxdWlyZSgnZDMtYXJyYXknKSwgcmVxdWlyZSgnZDMtcGF0aCcpKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtYXJyYXknLCAnZDMtcGF0aCddLCBmYWN0b3J5KSA6XG4gIChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pLGdsb2JhbC5kMyxnbG9iYWwuZDMpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLGQzQXJyYXksZDNQYXRoKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGNvcyA9IE1hdGguY29zO1xudmFyIHNpbiA9IE1hdGguc2luO1xudmFyIHBpID0gTWF0aC5QSTtcbnZhciBoYWxmUGkgPSBwaSAvIDI7XG52YXIgdGF1ID0gcGkgKiAyO1xudmFyIG1heCA9IE1hdGgubWF4O1xuXG5mdW5jdGlvbiBjb21wYXJlVmFsdWUoY29tcGFyZSkge1xuICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBjb21wYXJlKFxuICAgICAgYS5zb3VyY2UudmFsdWUgKyBhLnRhcmdldC52YWx1ZSxcbiAgICAgIGIuc291cmNlLnZhbHVlICsgYi50YXJnZXQudmFsdWVcbiAgICApO1xuICB9O1xufVxuXG52YXIgY2hvcmQgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHBhZEFuZ2xlID0gMCxcbiAgICAgIHNvcnRHcm91cHMgPSBudWxsLFxuICAgICAgc29ydFN1Ymdyb3VwcyA9IG51bGwsXG4gICAgICBzb3J0Q2hvcmRzID0gbnVsbDtcblxuICBmdW5jdGlvbiBjaG9yZChtYXRyaXgpIHtcbiAgICB2YXIgbiA9IG1hdHJpeC5sZW5ndGgsXG4gICAgICAgIGdyb3VwU3VtcyA9IFtdLFxuICAgICAgICBncm91cEluZGV4ID0gZDNBcnJheS5yYW5nZShuKSxcbiAgICAgICAgc3ViZ3JvdXBJbmRleCA9IFtdLFxuICAgICAgICBjaG9yZHMgPSBbXSxcbiAgICAgICAgZ3JvdXBzID0gY2hvcmRzLmdyb3VwcyA9IG5ldyBBcnJheShuKSxcbiAgICAgICAgc3ViZ3JvdXBzID0gbmV3IEFycmF5KG4gKiBuKSxcbiAgICAgICAgayxcbiAgICAgICAgeCxcbiAgICAgICAgeDAsXG4gICAgICAgIGR4LFxuICAgICAgICBpLFxuICAgICAgICBqO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgc3VtLlxuICAgIGsgPSAwLCBpID0gLTE7IHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICB4ID0gMCwgaiA9IC0xOyB3aGlsZSAoKytqIDwgbikge1xuICAgICAgICB4ICs9IG1hdHJpeFtpXVtqXTtcbiAgICAgIH1cbiAgICAgIGdyb3VwU3Vtcy5wdXNoKHgpO1xuICAgICAgc3ViZ3JvdXBJbmRleC5wdXNoKGQzQXJyYXkucmFuZ2UobikpO1xuICAgICAgayArPSB4O1xuICAgIH1cblxuICAgIC8vIFNvcnQgZ3JvdXBz4oCmXG4gICAgaWYgKHNvcnRHcm91cHMpIGdyb3VwSW5kZXguc29ydChmdW5jdGlvbihhLCBiKSB7XG4gICAgICByZXR1cm4gc29ydEdyb3Vwcyhncm91cFN1bXNbYV0sIGdyb3VwU3Vtc1tiXSk7XG4gICAgfSk7XG5cbiAgICAvLyBTb3J0IHN1Ymdyb3Vwc+KAplxuICAgIGlmIChzb3J0U3ViZ3JvdXBzKSBzdWJncm91cEluZGV4LmZvckVhY2goZnVuY3Rpb24oZCwgaSkge1xuICAgICAgZC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIHNvcnRTdWJncm91cHMobWF0cml4W2ldW2FdLCBtYXRyaXhbaV1bYl0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBDb252ZXJ0IHRoZSBzdW0gdG8gc2NhbGluZyBmYWN0b3IgZm9yIFswLCAycGldLlxuICAgIC8vIFRPRE8gQWxsb3cgc3RhcnQgYW5kIGVuZCBhbmdsZSB0byBiZSBzcGVjaWZpZWQ/XG4gICAgLy8gVE9ETyBBbGxvdyBwYWRkaW5nIHRvIGJlIHNwZWNpZmllZCBhcyBwZXJjZW50YWdlP1xuICAgIGsgPSBtYXgoMCwgdGF1IC0gcGFkQW5nbGUgKiBuKSAvIGs7XG4gICAgZHggPSBrID8gcGFkQW5nbGUgOiB0YXUgLyBuO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgc3RhcnQgYW5kIGVuZCBhbmdsZSBmb3IgZWFjaCBncm91cCBhbmQgc3ViZ3JvdXAuXG4gICAgLy8gTm90ZTogT3BlcmEgaGFzIGEgYnVnIHJlb3JkZXJpbmcgb2JqZWN0IGxpdGVyYWwgcHJvcGVydGllcyFcbiAgICB4ID0gMCwgaSA9IC0xOyB3aGlsZSAoKytpIDwgbikge1xuICAgICAgeDAgPSB4LCBqID0gLTE7IHdoaWxlICgrK2ogPCBuKSB7XG4gICAgICAgIHZhciBkaSA9IGdyb3VwSW5kZXhbaV0sXG4gICAgICAgICAgICBkaiA9IHN1Ymdyb3VwSW5kZXhbZGldW2pdLFxuICAgICAgICAgICAgdiA9IG1hdHJpeFtkaV1bZGpdLFxuICAgICAgICAgICAgYTAgPSB4LFxuICAgICAgICAgICAgYTEgPSB4ICs9IHYgKiBrO1xuICAgICAgICBzdWJncm91cHNbZGogKiBuICsgZGldID0ge1xuICAgICAgICAgIGluZGV4OiBkaSxcbiAgICAgICAgICBzdWJpbmRleDogZGosXG4gICAgICAgICAgc3RhcnRBbmdsZTogYTAsXG4gICAgICAgICAgZW5kQW5nbGU6IGExLFxuICAgICAgICAgIHZhbHVlOiB2XG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBncm91cHNbZGldID0ge1xuICAgICAgICBpbmRleDogZGksXG4gICAgICAgIHN0YXJ0QW5nbGU6IHgwLFxuICAgICAgICBlbmRBbmdsZTogeCxcbiAgICAgICAgdmFsdWU6IGdyb3VwU3Vtc1tkaV1cbiAgICAgIH07XG4gICAgICB4ICs9IGR4O1xuICAgIH1cblxuICAgIC8vIEdlbmVyYXRlIGNob3JkcyBmb3IgZWFjaCAobm9uLWVtcHR5KSBzdWJncm91cC1zdWJncm91cCBsaW5rLlxuICAgIGkgPSAtMTsgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGogPSBpIC0gMTsgd2hpbGUgKCsraiA8IG4pIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IHN1Ymdyb3Vwc1tqICogbiArIGldLFxuICAgICAgICAgICAgdGFyZ2V0ID0gc3ViZ3JvdXBzW2kgKiBuICsgal07XG4gICAgICAgIGlmIChzb3VyY2UudmFsdWUgfHwgdGFyZ2V0LnZhbHVlKSB7XG4gICAgICAgICAgY2hvcmRzLnB1c2goc291cmNlLnZhbHVlIDwgdGFyZ2V0LnZhbHVlXG4gICAgICAgICAgICAgID8ge3NvdXJjZTogdGFyZ2V0LCB0YXJnZXQ6IHNvdXJjZX1cbiAgICAgICAgICAgICAgOiB7c291cmNlOiBzb3VyY2UsIHRhcmdldDogdGFyZ2V0fSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc29ydENob3JkcyA/IGNob3Jkcy5zb3J0KHNvcnRDaG9yZHMpIDogY2hvcmRzO1xuICB9XG5cbiAgY2hvcmQucGFkQW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkQW5nbGUgPSBtYXgoMCwgXyksIGNob3JkKSA6IHBhZEFuZ2xlO1xuICB9O1xuXG4gIGNob3JkLnNvcnRHcm91cHMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc29ydEdyb3VwcyA9IF8sIGNob3JkKSA6IHNvcnRHcm91cHM7XG4gIH07XG5cbiAgY2hvcmQuc29ydFN1Ymdyb3VwcyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzb3J0U3ViZ3JvdXBzID0gXywgY2hvcmQpIDogc29ydFN1Ymdyb3VwcztcbiAgfTtcblxuICBjaG9yZC5zb3J0Q2hvcmRzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKF8gPT0gbnVsbCA/IHNvcnRDaG9yZHMgPSBudWxsIDogKHNvcnRDaG9yZHMgPSBjb21wYXJlVmFsdWUoXykpLl8gPSBfLCBjaG9yZCkgOiBzb3J0Q2hvcmRzICYmIHNvcnRDaG9yZHMuXztcbiAgfTtcblxuICByZXR1cm4gY2hvcmQ7XG59O1xuXG52YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxuZnVuY3Rpb24gZGVmYXVsdFNvdXJjZShkKSB7XG4gIHJldHVybiBkLnNvdXJjZTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFRhcmdldChkKSB7XG4gIHJldHVybiBkLnRhcmdldDtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFJhZGl1cyhkKSB7XG4gIHJldHVybiBkLnJhZGl1cztcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFN0YXJ0QW5nbGUoZCkge1xuICByZXR1cm4gZC5zdGFydEFuZ2xlO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0RW5kQW5nbGUoZCkge1xuICByZXR1cm4gZC5lbmRBbmdsZTtcbn1cblxudmFyIHJpYmJvbiA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc291cmNlID0gZGVmYXVsdFNvdXJjZSxcbiAgICAgIHRhcmdldCA9IGRlZmF1bHRUYXJnZXQsXG4gICAgICByYWRpdXMgPSBkZWZhdWx0UmFkaXVzLFxuICAgICAgc3RhcnRBbmdsZSA9IGRlZmF1bHRTdGFydEFuZ2xlLFxuICAgICAgZW5kQW5nbGUgPSBkZWZhdWx0RW5kQW5nbGUsXG4gICAgICBjb250ZXh0ID0gbnVsbDtcblxuICBmdW5jdGlvbiByaWJib24oKSB7XG4gICAgdmFyIGJ1ZmZlcixcbiAgICAgICAgYXJndiA9IHNsaWNlLmNhbGwoYXJndW1lbnRzKSxcbiAgICAgICAgcyA9IHNvdXJjZS5hcHBseSh0aGlzLCBhcmd2KSxcbiAgICAgICAgdCA9IHRhcmdldC5hcHBseSh0aGlzLCBhcmd2KSxcbiAgICAgICAgc3IgPSArcmFkaXVzLmFwcGx5KHRoaXMsIChhcmd2WzBdID0gcywgYXJndikpLFxuICAgICAgICBzYTAgPSBzdGFydEFuZ2xlLmFwcGx5KHRoaXMsIGFyZ3YpIC0gaGFsZlBpLFxuICAgICAgICBzYTEgPSBlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd2KSAtIGhhbGZQaSxcbiAgICAgICAgc3gwID0gc3IgKiBjb3Moc2EwKSxcbiAgICAgICAgc3kwID0gc3IgKiBzaW4oc2EwKSxcbiAgICAgICAgdHIgPSArcmFkaXVzLmFwcGx5KHRoaXMsIChhcmd2WzBdID0gdCwgYXJndikpLFxuICAgICAgICB0YTAgPSBzdGFydEFuZ2xlLmFwcGx5KHRoaXMsIGFyZ3YpIC0gaGFsZlBpLFxuICAgICAgICB0YTEgPSBlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd2KSAtIGhhbGZQaTtcblxuICAgIGlmICghY29udGV4dCkgY29udGV4dCA9IGJ1ZmZlciA9IGQzUGF0aC5wYXRoKCk7XG5cbiAgICBjb250ZXh0Lm1vdmVUbyhzeDAsIHN5MCk7XG4gICAgY29udGV4dC5hcmMoMCwgMCwgc3IsIHNhMCwgc2ExKTtcbiAgICBpZiAoc2EwICE9PSB0YTAgfHwgc2ExICE9PSB0YTEpIHsgLy8gVE9ETyBzciAhPT0gdHI/XG4gICAgICBjb250ZXh0LnF1YWRyYXRpY0N1cnZlVG8oMCwgMCwgdHIgKiBjb3ModGEwKSwgdHIgKiBzaW4odGEwKSk7XG4gICAgICBjb250ZXh0LmFyYygwLCAwLCB0ciwgdGEwLCB0YTEpO1xuICAgIH1cbiAgICBjb250ZXh0LnF1YWRyYXRpY0N1cnZlVG8oMCwgMCwgc3gwLCBzeTApO1xuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG5cbiAgICBpZiAoYnVmZmVyKSByZXR1cm4gY29udGV4dCA9IG51bGwsIGJ1ZmZlciArIFwiXCIgfHwgbnVsbDtcbiAgfVxuXG4gIHJpYmJvbi5yYWRpdXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIHJpYmJvbikgOiByYWRpdXM7XG4gIH07XG5cbiAgcmliYm9uLnN0YXJ0QW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RhcnRBbmdsZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCByaWJib24pIDogc3RhcnRBbmdsZTtcbiAgfTtcblxuICByaWJib24uZW5kQW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZW5kQW5nbGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgcmliYm9uKSA6IGVuZEFuZ2xlO1xuICB9O1xuXG4gIHJpYmJvbi5zb3VyY2UgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc291cmNlID0gXywgcmliYm9uKSA6IHNvdXJjZTtcbiAgfTtcblxuICByaWJib24udGFyZ2V0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRhcmdldCA9IF8sIHJpYmJvbikgOiB0YXJnZXQ7XG4gIH07XG5cbiAgcmliYm9uLmNvbnRleHQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoKGNvbnRleHQgPSBfID09IG51bGwgPyBudWxsIDogXyksIHJpYmJvbikgOiBjb250ZXh0O1xuICB9O1xuXG4gIHJldHVybiByaWJib247XG59O1xuXG5leHBvcnRzLmNob3JkID0gY2hvcmQ7XG5leHBvcnRzLnJpYmJvbiA9IHJpYmJvbjtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtY29sbGVjdGlvbi8gVmVyc2lvbiAxLjAuNC4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgcHJlZml4ID0gXCIkXCI7XG5cbmZ1bmN0aW9uIE1hcCgpIHt9XG5cbk1hcC5wcm90b3R5cGUgPSBtYXAucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogTWFwLFxuICBoYXM6IGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiAocHJlZml4ICsga2V5KSBpbiB0aGlzO1xuICB9LFxuICBnZXQ6IGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiB0aGlzW3ByZWZpeCArIGtleV07XG4gIH0sXG4gIHNldDogZnVuY3Rpb24oa2V5LCB2YWx1ZSkge1xuICAgIHRoaXNbcHJlZml4ICsga2V5XSA9IHZhbHVlO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICByZW1vdmU6IGZ1bmN0aW9uKGtleSkge1xuICAgIHZhciBwcm9wZXJ0eSA9IHByZWZpeCArIGtleTtcbiAgICByZXR1cm4gcHJvcGVydHkgaW4gdGhpcyAmJiBkZWxldGUgdGhpc1twcm9wZXJ0eV07XG4gIH0sXG4gIGNsZWFyOiBmdW5jdGlvbigpIHtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiB0aGlzKSBpZiAocHJvcGVydHlbMF0gPT09IHByZWZpeCkgZGVsZXRlIHRoaXNbcHJvcGVydHldO1xuICB9LFxuICBrZXlzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIga2V5cyA9IFtdO1xuICAgIGZvciAodmFyIHByb3BlcnR5IGluIHRoaXMpIGlmIChwcm9wZXJ0eVswXSA9PT0gcHJlZml4KSBrZXlzLnB1c2gocHJvcGVydHkuc2xpY2UoMSkpO1xuICAgIHJldHVybiBrZXlzO1xuICB9LFxuICB2YWx1ZXM6IGZ1bmN0aW9uKCkge1xuICAgIHZhciB2YWx1ZXMgPSBbXTtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiB0aGlzKSBpZiAocHJvcGVydHlbMF0gPT09IHByZWZpeCkgdmFsdWVzLnB1c2godGhpc1twcm9wZXJ0eV0pO1xuICAgIHJldHVybiB2YWx1ZXM7XG4gIH0sXG4gIGVudHJpZXM6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBlbnRyaWVzID0gW107XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpIGVudHJpZXMucHVzaCh7a2V5OiBwcm9wZXJ0eS5zbGljZSgxKSwgdmFsdWU6IHRoaXNbcHJvcGVydHldfSk7XG4gICAgcmV0dXJuIGVudHJpZXM7XG4gIH0sXG4gIHNpemU6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBzaXplID0gMDtcbiAgICBmb3IgKHZhciBwcm9wZXJ0eSBpbiB0aGlzKSBpZiAocHJvcGVydHlbMF0gPT09IHByZWZpeCkgKytzaXplO1xuICAgIHJldHVybiBzaXplO1xuICB9LFxuICBlbXB0eTogZnVuY3Rpb24oKSB7XG4gICAgZm9yICh2YXIgcHJvcGVydHkgaW4gdGhpcykgaWYgKHByb3BlcnR5WzBdID09PSBwcmVmaXgpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgZWFjaDogZnVuY3Rpb24oZikge1xuICAgIGZvciAodmFyIHByb3BlcnR5IGluIHRoaXMpIGlmIChwcm9wZXJ0eVswXSA9PT0gcHJlZml4KSBmKHRoaXNbcHJvcGVydHldLCBwcm9wZXJ0eS5zbGljZSgxKSwgdGhpcyk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIG1hcChvYmplY3QsIGYpIHtcbiAgdmFyIG1hcCA9IG5ldyBNYXA7XG5cbiAgLy8gQ29weSBjb25zdHJ1Y3Rvci5cbiAgaWYgKG9iamVjdCBpbnN0YW5jZW9mIE1hcCkgb2JqZWN0LmVhY2goZnVuY3Rpb24odmFsdWUsIGtleSkgeyBtYXAuc2V0KGtleSwgdmFsdWUpOyB9KTtcblxuICAvLyBJbmRleCBhcnJheSBieSBudW1lcmljIGluZGV4IG9yIHNwZWNpZmllZCBrZXkgZnVuY3Rpb24uXG4gIGVsc2UgaWYgKEFycmF5LmlzQXJyYXkob2JqZWN0KSkge1xuICAgIHZhciBpID0gLTEsXG4gICAgICAgIG4gPSBvYmplY3QubGVuZ3RoLFxuICAgICAgICBvO1xuXG4gICAgaWYgKGYgPT0gbnVsbCkgd2hpbGUgKCsraSA8IG4pIG1hcC5zZXQoaSwgb2JqZWN0W2ldKTtcbiAgICBlbHNlIHdoaWxlICgrK2kgPCBuKSBtYXAuc2V0KGYobyA9IG9iamVjdFtpXSwgaSwgb2JqZWN0KSwgbyk7XG4gIH1cblxuICAvLyBDb252ZXJ0IG9iamVjdCB0byBtYXAuXG4gIGVsc2UgaWYgKG9iamVjdCkgZm9yICh2YXIga2V5IGluIG9iamVjdCkgbWFwLnNldChrZXksIG9iamVjdFtrZXldKTtcblxuICByZXR1cm4gbWFwO1xufVxuXG52YXIgbmVzdCA9IGZ1bmN0aW9uKCkge1xuICB2YXIga2V5cyA9IFtdLFxuICAgICAgc29ydEtleXMgPSBbXSxcbiAgICAgIHNvcnRWYWx1ZXMsXG4gICAgICByb2xsdXAsXG4gICAgICBuZXN0O1xuXG4gIGZ1bmN0aW9uIGFwcGx5KGFycmF5LCBkZXB0aCwgY3JlYXRlUmVzdWx0LCBzZXRSZXN1bHQpIHtcbiAgICBpZiAoZGVwdGggPj0ga2V5cy5sZW5ndGgpIHtcbiAgICAgIGlmIChzb3J0VmFsdWVzICE9IG51bGwpIGFycmF5LnNvcnQoc29ydFZhbHVlcyk7XG4gICAgICByZXR1cm4gcm9sbHVwICE9IG51bGwgPyByb2xsdXAoYXJyYXkpIDogYXJyYXk7XG4gICAgfVxuXG4gICAgdmFyIGkgPSAtMSxcbiAgICAgICAgbiA9IGFycmF5Lmxlbmd0aCxcbiAgICAgICAga2V5ID0ga2V5c1tkZXB0aCsrXSxcbiAgICAgICAga2V5VmFsdWUsXG4gICAgICAgIHZhbHVlLFxuICAgICAgICB2YWx1ZXNCeUtleSA9IG1hcCgpLFxuICAgICAgICB2YWx1ZXMsXG4gICAgICAgIHJlc3VsdCA9IGNyZWF0ZVJlc3VsdCgpO1xuXG4gICAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICAgIGlmICh2YWx1ZXMgPSB2YWx1ZXNCeUtleS5nZXQoa2V5VmFsdWUgPSBrZXkodmFsdWUgPSBhcnJheVtpXSkgKyBcIlwiKSkge1xuICAgICAgICB2YWx1ZXMucHVzaCh2YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZXNCeUtleS5zZXQoa2V5VmFsdWUsIFt2YWx1ZV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhbHVlc0J5S2V5LmVhY2goZnVuY3Rpb24odmFsdWVzLCBrZXkpIHtcbiAgICAgIHNldFJlc3VsdChyZXN1bHQsIGtleSwgYXBwbHkodmFsdWVzLCBkZXB0aCwgY3JlYXRlUmVzdWx0LCBzZXRSZXN1bHQpKTtcbiAgICB9KTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBmdW5jdGlvbiBlbnRyaWVzKG1hcCQkMSwgZGVwdGgpIHtcbiAgICBpZiAoKytkZXB0aCA+IGtleXMubGVuZ3RoKSByZXR1cm4gbWFwJCQxO1xuICAgIHZhciBhcnJheSwgc29ydEtleSA9IHNvcnRLZXlzW2RlcHRoIC0gMV07XG4gICAgaWYgKHJvbGx1cCAhPSBudWxsICYmIGRlcHRoID49IGtleXMubGVuZ3RoKSBhcnJheSA9IG1hcCQkMS5lbnRyaWVzKCk7XG4gICAgZWxzZSBhcnJheSA9IFtdLCBtYXAkJDEuZWFjaChmdW5jdGlvbih2LCBrKSB7IGFycmF5LnB1c2goe2tleTogaywgdmFsdWVzOiBlbnRyaWVzKHYsIGRlcHRoKX0pOyB9KTtcbiAgICByZXR1cm4gc29ydEtleSAhPSBudWxsID8gYXJyYXkuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBzb3J0S2V5KGEua2V5LCBiLmtleSk7IH0pIDogYXJyYXk7XG4gIH1cblxuICByZXR1cm4gbmVzdCA9IHtcbiAgICBvYmplY3Q6IGZ1bmN0aW9uKGFycmF5KSB7IHJldHVybiBhcHBseShhcnJheSwgMCwgY3JlYXRlT2JqZWN0LCBzZXRPYmplY3QpOyB9LFxuICAgIG1hcDogZnVuY3Rpb24oYXJyYXkpIHsgcmV0dXJuIGFwcGx5KGFycmF5LCAwLCBjcmVhdGVNYXAsIHNldE1hcCk7IH0sXG4gICAgZW50cmllczogZnVuY3Rpb24oYXJyYXkpIHsgcmV0dXJuIGVudHJpZXMoYXBwbHkoYXJyYXksIDAsIGNyZWF0ZU1hcCwgc2V0TWFwKSwgMCk7IH0sXG4gICAga2V5OiBmdW5jdGlvbihkKSB7IGtleXMucHVzaChkKTsgcmV0dXJuIG5lc3Q7IH0sXG4gICAgc29ydEtleXM6IGZ1bmN0aW9uKG9yZGVyKSB7IHNvcnRLZXlzW2tleXMubGVuZ3RoIC0gMV0gPSBvcmRlcjsgcmV0dXJuIG5lc3Q7IH0sXG4gICAgc29ydFZhbHVlczogZnVuY3Rpb24ob3JkZXIpIHsgc29ydFZhbHVlcyA9IG9yZGVyOyByZXR1cm4gbmVzdDsgfSxcbiAgICByb2xsdXA6IGZ1bmN0aW9uKGYpIHsgcm9sbHVwID0gZjsgcmV0dXJuIG5lc3Q7IH1cbiAgfTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZU9iamVjdCgpIHtcbiAgcmV0dXJuIHt9O1xufVxuXG5mdW5jdGlvbiBzZXRPYmplY3Qob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gIG9iamVjdFtrZXldID0gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU1hcCgpIHtcbiAgcmV0dXJuIG1hcCgpO1xufVxuXG5mdW5jdGlvbiBzZXRNYXAobWFwJCQxLCBrZXksIHZhbHVlKSB7XG4gIG1hcCQkMS5zZXQoa2V5LCB2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIFNldCgpIHt9XG5cbnZhciBwcm90byA9IG1hcC5wcm90b3R5cGU7XG5cblNldC5wcm90b3R5cGUgPSBzZXQucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogU2V0LFxuICBoYXM6IHByb3RvLmhhcyxcbiAgYWRkOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHZhbHVlICs9IFwiXCI7XG4gICAgdGhpc1twcmVmaXggKyB2YWx1ZV0gPSB2YWx1ZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcmVtb3ZlOiBwcm90by5yZW1vdmUsXG4gIGNsZWFyOiBwcm90by5jbGVhcixcbiAgdmFsdWVzOiBwcm90by5rZXlzLFxuICBzaXplOiBwcm90by5zaXplLFxuICBlbXB0eTogcHJvdG8uZW1wdHksXG4gIGVhY2g6IHByb3RvLmVhY2hcbn07XG5cbmZ1bmN0aW9uIHNldChvYmplY3QsIGYpIHtcbiAgdmFyIHNldCA9IG5ldyBTZXQ7XG5cbiAgLy8gQ29weSBjb25zdHJ1Y3Rvci5cbiAgaWYgKG9iamVjdCBpbnN0YW5jZW9mIFNldCkgb2JqZWN0LmVhY2goZnVuY3Rpb24odmFsdWUpIHsgc2V0LmFkZCh2YWx1ZSk7IH0pO1xuXG4gIC8vIE90aGVyd2lzZSwgYXNzdW1lIGl04oCZcyBhbiBhcnJheS5cbiAgZWxzZSBpZiAob2JqZWN0KSB7XG4gICAgdmFyIGkgPSAtMSwgbiA9IG9iamVjdC5sZW5ndGg7XG4gICAgaWYgKGYgPT0gbnVsbCkgd2hpbGUgKCsraSA8IG4pIHNldC5hZGQob2JqZWN0W2ldKTtcbiAgICBlbHNlIHdoaWxlICgrK2kgPCBuKSBzZXQuYWRkKGYob2JqZWN0W2ldLCBpLCBvYmplY3QpKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbnZhciBrZXlzID0gZnVuY3Rpb24obWFwKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGtleSBpbiBtYXApIGtleXMucHVzaChrZXkpO1xuICByZXR1cm4ga2V5cztcbn07XG5cbnZhciB2YWx1ZXMgPSBmdW5jdGlvbihtYXApIHtcbiAgdmFyIHZhbHVlcyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gbWFwKSB2YWx1ZXMucHVzaChtYXBba2V5XSk7XG4gIHJldHVybiB2YWx1ZXM7XG59O1xuXG52YXIgZW50cmllcyA9IGZ1bmN0aW9uKG1hcCkge1xuICB2YXIgZW50cmllcyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gbWFwKSBlbnRyaWVzLnB1c2goe2tleToga2V5LCB2YWx1ZTogbWFwW2tleV19KTtcbiAgcmV0dXJuIGVudHJpZXM7XG59O1xuXG5leHBvcnRzLm5lc3QgPSBuZXN0O1xuZXhwb3J0cy5zZXQgPSBzZXQ7XG5leHBvcnRzLm1hcCA9IG1hcDtcbmV4cG9ydHMua2V5cyA9IGtleXM7XG5leHBvcnRzLnZhbHVlcyA9IHZhbHVlcztcbmV4cG9ydHMuZW50cmllcyA9IGVudHJpZXM7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWNvbG9yLyBWZXJzaW9uIDEuMC4zLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBkZWZpbmUgPSBmdW5jdGlvbihjb25zdHJ1Y3RvciwgZmFjdG9yeSwgcHJvdG90eXBlKSB7XG4gIGNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IGZhY3RvcnkucHJvdG90eXBlID0gcHJvdG90eXBlO1xuICBwcm90b3R5cGUuY29uc3RydWN0b3IgPSBjb25zdHJ1Y3Rvcjtcbn07XG5cbmZ1bmN0aW9uIGV4dGVuZChwYXJlbnQsIGRlZmluaXRpb24pIHtcbiAgdmFyIHByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUocGFyZW50LnByb3RvdHlwZSk7XG4gIGZvciAodmFyIGtleSBpbiBkZWZpbml0aW9uKSBwcm90b3R5cGVba2V5XSA9IGRlZmluaXRpb25ba2V5XTtcbiAgcmV0dXJuIHByb3RvdHlwZTtcbn1cblxuZnVuY3Rpb24gQ29sb3IoKSB7fVxuXG52YXIgZGFya2VyID0gMC43O1xudmFyIGJyaWdodGVyID0gMSAvIGRhcmtlcjtcblxudmFyIHJlSSA9IFwiXFxcXHMqKFsrLV0/XFxcXGQrKVxcXFxzKlwiO1xudmFyIHJlTiA9IFwiXFxcXHMqKFsrLV0/XFxcXGQqXFxcXC4/XFxcXGQrKD86W2VFXVsrLV0/XFxcXGQrKT8pXFxcXHMqXCI7XG52YXIgcmVQID0gXCJcXFxccyooWystXT9cXFxcZCpcXFxcLj9cXFxcZCsoPzpbZUVdWystXT9cXFxcZCspPyklXFxcXHMqXCI7XG52YXIgcmVIZXgzID0gL14jKFswLTlhLWZdezN9KSQvO1xudmFyIHJlSGV4NiA9IC9eIyhbMC05YS1mXXs2fSkkLztcbnZhciByZVJnYkludGVnZXIgPSBuZXcgUmVnRXhwKFwiXnJnYlxcXFwoXCIgKyBbcmVJLCByZUksIHJlSV0gKyBcIlxcXFwpJFwiKTtcbnZhciByZVJnYlBlcmNlbnQgPSBuZXcgUmVnRXhwKFwiXnJnYlxcXFwoXCIgKyBbcmVQLCByZVAsIHJlUF0gKyBcIlxcXFwpJFwiKTtcbnZhciByZVJnYmFJbnRlZ2VyID0gbmV3IFJlZ0V4cChcIl5yZ2JhXFxcXChcIiArIFtyZUksIHJlSSwgcmVJLCByZU5dICsgXCJcXFxcKSRcIik7XG52YXIgcmVSZ2JhUGVyY2VudCA9IG5ldyBSZWdFeHAoXCJecmdiYVxcXFwoXCIgKyBbcmVQLCByZVAsIHJlUCwgcmVOXSArIFwiXFxcXCkkXCIpO1xudmFyIHJlSHNsUGVyY2VudCA9IG5ldyBSZWdFeHAoXCJeaHNsXFxcXChcIiArIFtyZU4sIHJlUCwgcmVQXSArIFwiXFxcXCkkXCIpO1xudmFyIHJlSHNsYVBlcmNlbnQgPSBuZXcgUmVnRXhwKFwiXmhzbGFcXFxcKFwiICsgW3JlTiwgcmVQLCByZVAsIHJlTl0gKyBcIlxcXFwpJFwiKTtcblxudmFyIG5hbWVkID0ge1xuICBhbGljZWJsdWU6IDB4ZjBmOGZmLFxuICBhbnRpcXVld2hpdGU6IDB4ZmFlYmQ3LFxuICBhcXVhOiAweDAwZmZmZixcbiAgYXF1YW1hcmluZTogMHg3ZmZmZDQsXG4gIGF6dXJlOiAweGYwZmZmZixcbiAgYmVpZ2U6IDB4ZjVmNWRjLFxuICBiaXNxdWU6IDB4ZmZlNGM0LFxuICBibGFjazogMHgwMDAwMDAsXG4gIGJsYW5jaGVkYWxtb25kOiAweGZmZWJjZCxcbiAgYmx1ZTogMHgwMDAwZmYsXG4gIGJsdWV2aW9sZXQ6IDB4OGEyYmUyLFxuICBicm93bjogMHhhNTJhMmEsXG4gIGJ1cmx5d29vZDogMHhkZWI4ODcsXG4gIGNhZGV0Ymx1ZTogMHg1ZjllYTAsXG4gIGNoYXJ0cmV1c2U6IDB4N2ZmZjAwLFxuICBjaG9jb2xhdGU6IDB4ZDI2OTFlLFxuICBjb3JhbDogMHhmZjdmNTAsXG4gIGNvcm5mbG93ZXJibHVlOiAweDY0OTVlZCxcbiAgY29ybnNpbGs6IDB4ZmZmOGRjLFxuICBjcmltc29uOiAweGRjMTQzYyxcbiAgY3lhbjogMHgwMGZmZmYsXG4gIGRhcmtibHVlOiAweDAwMDA4YixcbiAgZGFya2N5YW46IDB4MDA4YjhiLFxuICBkYXJrZ29sZGVucm9kOiAweGI4ODYwYixcbiAgZGFya2dyYXk6IDB4YTlhOWE5LFxuICBkYXJrZ3JlZW46IDB4MDA2NDAwLFxuICBkYXJrZ3JleTogMHhhOWE5YTksXG4gIGRhcmtraGFraTogMHhiZGI3NmIsXG4gIGRhcmttYWdlbnRhOiAweDhiMDA4YixcbiAgZGFya29saXZlZ3JlZW46IDB4NTU2YjJmLFxuICBkYXJrb3JhbmdlOiAweGZmOGMwMCxcbiAgZGFya29yY2hpZDogMHg5OTMyY2MsXG4gIGRhcmtyZWQ6IDB4OGIwMDAwLFxuICBkYXJrc2FsbW9uOiAweGU5OTY3YSxcbiAgZGFya3NlYWdyZWVuOiAweDhmYmM4ZixcbiAgZGFya3NsYXRlYmx1ZTogMHg0ODNkOGIsXG4gIGRhcmtzbGF0ZWdyYXk6IDB4MmY0ZjRmLFxuICBkYXJrc2xhdGVncmV5OiAweDJmNGY0ZixcbiAgZGFya3R1cnF1b2lzZTogMHgwMGNlZDEsXG4gIGRhcmt2aW9sZXQ6IDB4OTQwMGQzLFxuICBkZWVwcGluazogMHhmZjE0OTMsXG4gIGRlZXBza3libHVlOiAweDAwYmZmZixcbiAgZGltZ3JheTogMHg2OTY5NjksXG4gIGRpbWdyZXk6IDB4Njk2OTY5LFxuICBkb2RnZXJibHVlOiAweDFlOTBmZixcbiAgZmlyZWJyaWNrOiAweGIyMjIyMixcbiAgZmxvcmFsd2hpdGU6IDB4ZmZmYWYwLFxuICBmb3Jlc3RncmVlbjogMHgyMjhiMjIsXG4gIGZ1Y2hzaWE6IDB4ZmYwMGZmLFxuICBnYWluc2Jvcm86IDB4ZGNkY2RjLFxuICBnaG9zdHdoaXRlOiAweGY4ZjhmZixcbiAgZ29sZDogMHhmZmQ3MDAsXG4gIGdvbGRlbnJvZDogMHhkYWE1MjAsXG4gIGdyYXk6IDB4ODA4MDgwLFxuICBncmVlbjogMHgwMDgwMDAsXG4gIGdyZWVueWVsbG93OiAweGFkZmYyZixcbiAgZ3JleTogMHg4MDgwODAsXG4gIGhvbmV5ZGV3OiAweGYwZmZmMCxcbiAgaG90cGluazogMHhmZjY5YjQsXG4gIGluZGlhbnJlZDogMHhjZDVjNWMsXG4gIGluZGlnbzogMHg0YjAwODIsXG4gIGl2b3J5OiAweGZmZmZmMCxcbiAga2hha2k6IDB4ZjBlNjhjLFxuICBsYXZlbmRlcjogMHhlNmU2ZmEsXG4gIGxhdmVuZGVyYmx1c2g6IDB4ZmZmMGY1LFxuICBsYXduZ3JlZW46IDB4N2NmYzAwLFxuICBsZW1vbmNoaWZmb246IDB4ZmZmYWNkLFxuICBsaWdodGJsdWU6IDB4YWRkOGU2LFxuICBsaWdodGNvcmFsOiAweGYwODA4MCxcbiAgbGlnaHRjeWFuOiAweGUwZmZmZixcbiAgbGlnaHRnb2xkZW5yb2R5ZWxsb3c6IDB4ZmFmYWQyLFxuICBsaWdodGdyYXk6IDB4ZDNkM2QzLFxuICBsaWdodGdyZWVuOiAweDkwZWU5MCxcbiAgbGlnaHRncmV5OiAweGQzZDNkMyxcbiAgbGlnaHRwaW5rOiAweGZmYjZjMSxcbiAgbGlnaHRzYWxtb246IDB4ZmZhMDdhLFxuICBsaWdodHNlYWdyZWVuOiAweDIwYjJhYSxcbiAgbGlnaHRza3libHVlOiAweDg3Y2VmYSxcbiAgbGlnaHRzbGF0ZWdyYXk6IDB4Nzc4ODk5LFxuICBsaWdodHNsYXRlZ3JleTogMHg3Nzg4OTksXG4gIGxpZ2h0c3RlZWxibHVlOiAweGIwYzRkZSxcbiAgbGlnaHR5ZWxsb3c6IDB4ZmZmZmUwLFxuICBsaW1lOiAweDAwZmYwMCxcbiAgbGltZWdyZWVuOiAweDMyY2QzMixcbiAgbGluZW46IDB4ZmFmMGU2LFxuICBtYWdlbnRhOiAweGZmMDBmZixcbiAgbWFyb29uOiAweDgwMDAwMCxcbiAgbWVkaXVtYXF1YW1hcmluZTogMHg2NmNkYWEsXG4gIG1lZGl1bWJsdWU6IDB4MDAwMGNkLFxuICBtZWRpdW1vcmNoaWQ6IDB4YmE1NWQzLFxuICBtZWRpdW1wdXJwbGU6IDB4OTM3MGRiLFxuICBtZWRpdW1zZWFncmVlbjogMHgzY2IzNzEsXG4gIG1lZGl1bXNsYXRlYmx1ZTogMHg3YjY4ZWUsXG4gIG1lZGl1bXNwcmluZ2dyZWVuOiAweDAwZmE5YSxcbiAgbWVkaXVtdHVycXVvaXNlOiAweDQ4ZDFjYyxcbiAgbWVkaXVtdmlvbGV0cmVkOiAweGM3MTU4NSxcbiAgbWlkbmlnaHRibHVlOiAweDE5MTk3MCxcbiAgbWludGNyZWFtOiAweGY1ZmZmYSxcbiAgbWlzdHlyb3NlOiAweGZmZTRlMSxcbiAgbW9jY2FzaW46IDB4ZmZlNGI1LFxuICBuYXZham93aGl0ZTogMHhmZmRlYWQsXG4gIG5hdnk6IDB4MDAwMDgwLFxuICBvbGRsYWNlOiAweGZkZjVlNixcbiAgb2xpdmU6IDB4ODA4MDAwLFxuICBvbGl2ZWRyYWI6IDB4NmI4ZTIzLFxuICBvcmFuZ2U6IDB4ZmZhNTAwLFxuICBvcmFuZ2VyZWQ6IDB4ZmY0NTAwLFxuICBvcmNoaWQ6IDB4ZGE3MGQ2LFxuICBwYWxlZ29sZGVucm9kOiAweGVlZThhYSxcbiAgcGFsZWdyZWVuOiAweDk4ZmI5OCxcbiAgcGFsZXR1cnF1b2lzZTogMHhhZmVlZWUsXG4gIHBhbGV2aW9sZXRyZWQ6IDB4ZGI3MDkzLFxuICBwYXBheWF3aGlwOiAweGZmZWZkNSxcbiAgcGVhY2hwdWZmOiAweGZmZGFiOSxcbiAgcGVydTogMHhjZDg1M2YsXG4gIHBpbms6IDB4ZmZjMGNiLFxuICBwbHVtOiAweGRkYTBkZCxcbiAgcG93ZGVyYmx1ZTogMHhiMGUwZTYsXG4gIHB1cnBsZTogMHg4MDAwODAsXG4gIHJlYmVjY2FwdXJwbGU6IDB4NjYzMzk5LFxuICByZWQ6IDB4ZmYwMDAwLFxuICByb3N5YnJvd246IDB4YmM4ZjhmLFxuICByb3lhbGJsdWU6IDB4NDE2OWUxLFxuICBzYWRkbGVicm93bjogMHg4YjQ1MTMsXG4gIHNhbG1vbjogMHhmYTgwNzIsXG4gIHNhbmR5YnJvd246IDB4ZjRhNDYwLFxuICBzZWFncmVlbjogMHgyZThiNTcsXG4gIHNlYXNoZWxsOiAweGZmZjVlZSxcbiAgc2llbm5hOiAweGEwNTIyZCxcbiAgc2lsdmVyOiAweGMwYzBjMCxcbiAgc2t5Ymx1ZTogMHg4N2NlZWIsXG4gIHNsYXRlYmx1ZTogMHg2YTVhY2QsXG4gIHNsYXRlZ3JheTogMHg3MDgwOTAsXG4gIHNsYXRlZ3JleTogMHg3MDgwOTAsXG4gIHNub3c6IDB4ZmZmYWZhLFxuICBzcHJpbmdncmVlbjogMHgwMGZmN2YsXG4gIHN0ZWVsYmx1ZTogMHg0NjgyYjQsXG4gIHRhbjogMHhkMmI0OGMsXG4gIHRlYWw6IDB4MDA4MDgwLFxuICB0aGlzdGxlOiAweGQ4YmZkOCxcbiAgdG9tYXRvOiAweGZmNjM0NyxcbiAgdHVycXVvaXNlOiAweDQwZTBkMCxcbiAgdmlvbGV0OiAweGVlODJlZSxcbiAgd2hlYXQ6IDB4ZjVkZWIzLFxuICB3aGl0ZTogMHhmZmZmZmYsXG4gIHdoaXRlc21va2U6IDB4ZjVmNWY1LFxuICB5ZWxsb3c6IDB4ZmZmZjAwLFxuICB5ZWxsb3dncmVlbjogMHg5YWNkMzJcbn07XG5cbmRlZmluZShDb2xvciwgY29sb3IsIHtcbiAgZGlzcGxheWFibGU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnJnYigpLmRpc3BsYXlhYmxlKCk7XG4gIH0sXG4gIHRvU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5yZ2IoKSArIFwiXCI7XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiBjb2xvcihmb3JtYXQpIHtcbiAgdmFyIG07XG4gIGZvcm1hdCA9IChmb3JtYXQgKyBcIlwiKS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgcmV0dXJuIChtID0gcmVIZXgzLmV4ZWMoZm9ybWF0KSkgPyAobSA9IHBhcnNlSW50KG1bMV0sIDE2KSwgbmV3IFJnYigobSA+PiA4ICYgMHhmKSB8IChtID4+IDQgJiAweDBmMCksIChtID4+IDQgJiAweGYpIHwgKG0gJiAweGYwKSwgKChtICYgMHhmKSA8PCA0KSB8IChtICYgMHhmKSwgMSkpIC8vICNmMDBcbiAgICAgIDogKG0gPSByZUhleDYuZXhlYyhmb3JtYXQpKSA/IHJnYm4ocGFyc2VJbnQobVsxXSwgMTYpKSAvLyAjZmYwMDAwXG4gICAgICA6IChtID0gcmVSZ2JJbnRlZ2VyLmV4ZWMoZm9ybWF0KSkgPyBuZXcgUmdiKG1bMV0sIG1bMl0sIG1bM10sIDEpIC8vIHJnYigyNTUsIDAsIDApXG4gICAgICA6IChtID0gcmVSZ2JQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyBuZXcgUmdiKG1bMV0gKiAyNTUgLyAxMDAsIG1bMl0gKiAyNTUgLyAxMDAsIG1bM10gKiAyNTUgLyAxMDAsIDEpIC8vIHJnYigxMDAlLCAwJSwgMCUpXG4gICAgICA6IChtID0gcmVSZ2JhSW50ZWdlci5leGVjKGZvcm1hdCkpID8gcmdiYShtWzFdLCBtWzJdLCBtWzNdLCBtWzRdKSAvLyByZ2JhKDI1NSwgMCwgMCwgMSlcbiAgICAgIDogKG0gPSByZVJnYmFQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyByZ2JhKG1bMV0gKiAyNTUgLyAxMDAsIG1bMl0gKiAyNTUgLyAxMDAsIG1bM10gKiAyNTUgLyAxMDAsIG1bNF0pIC8vIHJnYigxMDAlLCAwJSwgMCUsIDEpXG4gICAgICA6IChtID0gcmVIc2xQZXJjZW50LmV4ZWMoZm9ybWF0KSkgPyBoc2xhKG1bMV0sIG1bMl0gLyAxMDAsIG1bM10gLyAxMDAsIDEpIC8vIGhzbCgxMjAsIDUwJSwgNTAlKVxuICAgICAgOiAobSA9IHJlSHNsYVBlcmNlbnQuZXhlYyhmb3JtYXQpKSA/IGhzbGEobVsxXSwgbVsyXSAvIDEwMCwgbVszXSAvIDEwMCwgbVs0XSkgLy8gaHNsYSgxMjAsIDUwJSwgNTAlLCAxKVxuICAgICAgOiBuYW1lZC5oYXNPd25Qcm9wZXJ0eShmb3JtYXQpID8gcmdibihuYW1lZFtmb3JtYXRdKVxuICAgICAgOiBmb3JtYXQgPT09IFwidHJhbnNwYXJlbnRcIiA/IG5ldyBSZ2IoTmFOLCBOYU4sIE5hTiwgMClcbiAgICAgIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gcmdibihuKSB7XG4gIHJldHVybiBuZXcgUmdiKG4gPj4gMTYgJiAweGZmLCBuID4+IDggJiAweGZmLCBuICYgMHhmZiwgMSk7XG59XG5cbmZ1bmN0aW9uIHJnYmEociwgZywgYiwgYSkge1xuICBpZiAoYSA8PSAwKSByID0gZyA9IGIgPSBOYU47XG4gIHJldHVybiBuZXcgUmdiKHIsIGcsIGIsIGEpO1xufVxuXG5mdW5jdGlvbiByZ2JDb252ZXJ0KG8pIHtcbiAgaWYgKCEobyBpbnN0YW5jZW9mIENvbG9yKSkgbyA9IGNvbG9yKG8pO1xuICBpZiAoIW8pIHJldHVybiBuZXcgUmdiO1xuICBvID0gby5yZ2IoKTtcbiAgcmV0dXJuIG5ldyBSZ2Ioby5yLCBvLmcsIG8uYiwgby5vcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gcmdiKHIsIGcsIGIsIG9wYWNpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPT09IDEgPyByZ2JDb252ZXJ0KHIpIDogbmV3IFJnYihyLCBnLCBiLCBvcGFjaXR5ID09IG51bGwgPyAxIDogb3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIFJnYihyLCBnLCBiLCBvcGFjaXR5KSB7XG4gIHRoaXMuciA9ICtyO1xuICB0aGlzLmcgPSArZztcbiAgdGhpcy5iID0gK2I7XG4gIHRoaXMub3BhY2l0eSA9ICtvcGFjaXR5O1xufVxuXG5kZWZpbmUoUmdiLCByZ2IsIGV4dGVuZChDb2xvciwge1xuICBicmlnaHRlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBicmlnaHRlciA6IE1hdGgucG93KGJyaWdodGVyLCBrKTtcbiAgICByZXR1cm4gbmV3IFJnYih0aGlzLnIgKiBrLCB0aGlzLmcgKiBrLCB0aGlzLmIgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICBkYXJrZXI6IGZ1bmN0aW9uKGspIHtcbiAgICBrID0gayA9PSBudWxsID8gZGFya2VyIDogTWF0aC5wb3coZGFya2VyLCBrKTtcbiAgICByZXR1cm4gbmV3IFJnYih0aGlzLnIgKiBrLCB0aGlzLmcgKiBrLCB0aGlzLmIgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuICBkaXNwbGF5YWJsZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICgwIDw9IHRoaXMuciAmJiB0aGlzLnIgPD0gMjU1KVxuICAgICAgICAmJiAoMCA8PSB0aGlzLmcgJiYgdGhpcy5nIDw9IDI1NSlcbiAgICAgICAgJiYgKDAgPD0gdGhpcy5iICYmIHRoaXMuYiA8PSAyNTUpXG4gICAgICAgICYmICgwIDw9IHRoaXMub3BhY2l0eSAmJiB0aGlzLm9wYWNpdHkgPD0gMSk7XG4gIH0sXG4gIHRvU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgYSA9IHRoaXMub3BhY2l0eTsgYSA9IGlzTmFOKGEpID8gMSA6IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGEpKTtcbiAgICByZXR1cm4gKGEgPT09IDEgPyBcInJnYihcIiA6IFwicmdiYShcIilcbiAgICAgICAgKyBNYXRoLm1heCgwLCBNYXRoLm1pbigyNTUsIE1hdGgucm91bmQodGhpcy5yKSB8fCAwKSkgKyBcIiwgXCJcbiAgICAgICAgKyBNYXRoLm1heCgwLCBNYXRoLm1pbigyNTUsIE1hdGgucm91bmQodGhpcy5nKSB8fCAwKSkgKyBcIiwgXCJcbiAgICAgICAgKyBNYXRoLm1heCgwLCBNYXRoLm1pbigyNTUsIE1hdGgucm91bmQodGhpcy5iKSB8fCAwKSlcbiAgICAgICAgKyAoYSA9PT0gMSA/IFwiKVwiIDogXCIsIFwiICsgYSArIFwiKVwiKTtcbiAgfVxufSkpO1xuXG5mdW5jdGlvbiBoc2xhKGgsIHMsIGwsIGEpIHtcbiAgaWYgKGEgPD0gMCkgaCA9IHMgPSBsID0gTmFOO1xuICBlbHNlIGlmIChsIDw9IDAgfHwgbCA+PSAxKSBoID0gcyA9IE5hTjtcbiAgZWxzZSBpZiAocyA8PSAwKSBoID0gTmFOO1xuICByZXR1cm4gbmV3IEhzbChoLCBzLCBsLCBhKTtcbn1cblxuZnVuY3Rpb24gaHNsQ29udmVydChvKSB7XG4gIGlmIChvIGluc3RhbmNlb2YgSHNsKSByZXR1cm4gbmV3IEhzbChvLmgsIG8ucywgby5sLCBvLm9wYWNpdHkpO1xuICBpZiAoIShvIGluc3RhbmNlb2YgQ29sb3IpKSBvID0gY29sb3Iobyk7XG4gIGlmICghbykgcmV0dXJuIG5ldyBIc2w7XG4gIGlmIChvIGluc3RhbmNlb2YgSHNsKSByZXR1cm4gbztcbiAgbyA9IG8ucmdiKCk7XG4gIHZhciByID0gby5yIC8gMjU1LFxuICAgICAgZyA9IG8uZyAvIDI1NSxcbiAgICAgIGIgPSBvLmIgLyAyNTUsXG4gICAgICBtaW4gPSBNYXRoLm1pbihyLCBnLCBiKSxcbiAgICAgIG1heCA9IE1hdGgubWF4KHIsIGcsIGIpLFxuICAgICAgaCA9IE5hTixcbiAgICAgIHMgPSBtYXggLSBtaW4sXG4gICAgICBsID0gKG1heCArIG1pbikgLyAyO1xuICBpZiAocykge1xuICAgIGlmIChyID09PSBtYXgpIGggPSAoZyAtIGIpIC8gcyArIChnIDwgYikgKiA2O1xuICAgIGVsc2UgaWYgKGcgPT09IG1heCkgaCA9IChiIC0gcikgLyBzICsgMjtcbiAgICBlbHNlIGggPSAociAtIGcpIC8gcyArIDQ7XG4gICAgcyAvPSBsIDwgMC41ID8gbWF4ICsgbWluIDogMiAtIG1heCAtIG1pbjtcbiAgICBoICo9IDYwO1xuICB9IGVsc2Uge1xuICAgIHMgPSBsID4gMCAmJiBsIDwgMSA/IDAgOiBoO1xuICB9XG4gIHJldHVybiBuZXcgSHNsKGgsIHMsIGwsIG8ub3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIGhzbChoLCBzLCBsLCBvcGFjaXR5KSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID09PSAxID8gaHNsQ29udmVydChoKSA6IG5ldyBIc2woaCwgcywgbCwgb3BhY2l0eSA9PSBudWxsID8gMSA6IG9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBIc2woaCwgcywgbCwgb3BhY2l0eSkge1xuICB0aGlzLmggPSAraDtcbiAgdGhpcy5zID0gK3M7XG4gIHRoaXMubCA9ICtsO1xuICB0aGlzLm9wYWNpdHkgPSArb3BhY2l0eTtcbn1cblxuZGVmaW5lKEhzbCwgaHNsLCBleHRlbmQoQ29sb3IsIHtcbiAgYnJpZ2h0ZXI6IGZ1bmN0aW9uKGspIHtcbiAgICBrID0gayA9PSBudWxsID8gYnJpZ2h0ZXIgOiBNYXRoLnBvdyhicmlnaHRlciwgayk7XG4gICAgcmV0dXJuIG5ldyBIc2wodGhpcy5oLCB0aGlzLnMsIHRoaXMubCAqIGssIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIGRhcmtlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBkYXJrZXIgOiBNYXRoLnBvdyhkYXJrZXIsIGspO1xuICAgIHJldHVybiBuZXcgSHNsKHRoaXMuaCwgdGhpcy5zLCB0aGlzLmwgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoID0gdGhpcy5oICUgMzYwICsgKHRoaXMuaCA8IDApICogMzYwLFxuICAgICAgICBzID0gaXNOYU4oaCkgfHwgaXNOYU4odGhpcy5zKSA/IDAgOiB0aGlzLnMsXG4gICAgICAgIGwgPSB0aGlzLmwsXG4gICAgICAgIG0yID0gbCArIChsIDwgMC41ID8gbCA6IDEgLSBsKSAqIHMsXG4gICAgICAgIG0xID0gMiAqIGwgLSBtMjtcbiAgICByZXR1cm4gbmV3IFJnYihcbiAgICAgIGhzbDJyZ2IoaCA+PSAyNDAgPyBoIC0gMjQwIDogaCArIDEyMCwgbTEsIG0yKSxcbiAgICAgIGhzbDJyZ2IoaCwgbTEsIG0yKSxcbiAgICAgIGhzbDJyZ2IoaCA8IDEyMCA/IGggKyAyNDAgOiBoIC0gMTIwLCBtMSwgbTIpLFxuICAgICAgdGhpcy5vcGFjaXR5XG4gICAgKTtcbiAgfSxcbiAgZGlzcGxheWFibGU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiAoMCA8PSB0aGlzLnMgJiYgdGhpcy5zIDw9IDEgfHwgaXNOYU4odGhpcy5zKSlcbiAgICAgICAgJiYgKDAgPD0gdGhpcy5sICYmIHRoaXMubCA8PSAxKVxuICAgICAgICAmJiAoMCA8PSB0aGlzLm9wYWNpdHkgJiYgdGhpcy5vcGFjaXR5IDw9IDEpO1xuICB9XG59KSk7XG5cbi8qIEZyb20gRnZEIDEzLjM3LCBDU1MgQ29sb3IgTW9kdWxlIExldmVsIDMgKi9cbmZ1bmN0aW9uIGhzbDJyZ2IoaCwgbTEsIG0yKSB7XG4gIHJldHVybiAoaCA8IDYwID8gbTEgKyAobTIgLSBtMSkgKiBoIC8gNjBcbiAgICAgIDogaCA8IDE4MCA/IG0yXG4gICAgICA6IGggPCAyNDAgPyBtMSArIChtMiAtIG0xKSAqICgyNDAgLSBoKSAvIDYwXG4gICAgICA6IG0xKSAqIDI1NTtcbn1cblxudmFyIGRlZzJyYWQgPSBNYXRoLlBJIC8gMTgwO1xudmFyIHJhZDJkZWcgPSAxODAgLyBNYXRoLlBJO1xuXG52YXIgS24gPSAxODtcbnZhciBYbiA9IDAuOTUwNDcwO1xudmFyIFluID0gMTtcbnZhciBabiA9IDEuMDg4ODMwO1xudmFyIHQwID0gNCAvIDI5O1xudmFyIHQxID0gNiAvIDI5O1xudmFyIHQyID0gMyAqIHQxICogdDE7XG52YXIgdDMgPSB0MSAqIHQxICogdDE7XG5cbmZ1bmN0aW9uIGxhYkNvbnZlcnQobykge1xuICBpZiAobyBpbnN0YW5jZW9mIExhYikgcmV0dXJuIG5ldyBMYWIoby5sLCBvLmEsIG8uYiwgby5vcGFjaXR5KTtcbiAgaWYgKG8gaW5zdGFuY2VvZiBIY2wpIHtcbiAgICB2YXIgaCA9IG8uaCAqIGRlZzJyYWQ7XG4gICAgcmV0dXJuIG5ldyBMYWIoby5sLCBNYXRoLmNvcyhoKSAqIG8uYywgTWF0aC5zaW4oaCkgKiBvLmMsIG8ub3BhY2l0eSk7XG4gIH1cbiAgaWYgKCEobyBpbnN0YW5jZW9mIFJnYikpIG8gPSByZ2JDb252ZXJ0KG8pO1xuICB2YXIgYiA9IHJnYjJ4eXooby5yKSxcbiAgICAgIGEgPSByZ2IyeHl6KG8uZyksXG4gICAgICBsID0gcmdiMnh5eihvLmIpLFxuICAgICAgeCA9IHh5ejJsYWIoKDAuNDEyNDU2NCAqIGIgKyAwLjM1NzU3NjEgKiBhICsgMC4xODA0Mzc1ICogbCkgLyBYbiksXG4gICAgICB5ID0geHl6MmxhYigoMC4yMTI2NzI5ICogYiArIDAuNzE1MTUyMiAqIGEgKyAwLjA3MjE3NTAgKiBsKSAvIFluKSxcbiAgICAgIHogPSB4eXoybGFiKCgwLjAxOTMzMzkgKiBiICsgMC4xMTkxOTIwICogYSArIDAuOTUwMzA0MSAqIGwpIC8gWm4pO1xuICByZXR1cm4gbmV3IExhYigxMTYgKiB5IC0gMTYsIDUwMCAqICh4IC0geSksIDIwMCAqICh5IC0geiksIG8ub3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIGxhYihsLCBhLCBiLCBvcGFjaXR5KSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID09PSAxID8gbGFiQ29udmVydChsKSA6IG5ldyBMYWIobCwgYSwgYiwgb3BhY2l0eSA9PSBudWxsID8gMSA6IG9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBMYWIobCwgYSwgYiwgb3BhY2l0eSkge1xuICB0aGlzLmwgPSArbDtcbiAgdGhpcy5hID0gK2E7XG4gIHRoaXMuYiA9ICtiO1xuICB0aGlzLm9wYWNpdHkgPSArb3BhY2l0eTtcbn1cblxuZGVmaW5lKExhYiwgbGFiLCBleHRlbmQoQ29sb3IsIHtcbiAgYnJpZ2h0ZXI6IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IExhYih0aGlzLmwgKyBLbiAqIChrID09IG51bGwgPyAxIDogayksIHRoaXMuYSwgdGhpcy5iLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICBkYXJrZXI6IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gbmV3IExhYih0aGlzLmwgLSBLbiAqIChrID09IG51bGwgPyAxIDogayksIHRoaXMuYSwgdGhpcy5iLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHZhciB5ID0gKHRoaXMubCArIDE2KSAvIDExNixcbiAgICAgICAgeCA9IGlzTmFOKHRoaXMuYSkgPyB5IDogeSArIHRoaXMuYSAvIDUwMCxcbiAgICAgICAgeiA9IGlzTmFOKHRoaXMuYikgPyB5IDogeSAtIHRoaXMuYiAvIDIwMDtcbiAgICB5ID0gWW4gKiBsYWIyeHl6KHkpO1xuICAgIHggPSBYbiAqIGxhYjJ4eXooeCk7XG4gICAgeiA9IFpuICogbGFiMnh5eih6KTtcbiAgICByZXR1cm4gbmV3IFJnYihcbiAgICAgIHh5ejJyZ2IoIDMuMjQwNDU0MiAqIHggLSAxLjUzNzEzODUgKiB5IC0gMC40OTg1MzE0ICogeiksIC8vIEQ2NSAtPiBzUkdCXG4gICAgICB4eXoycmdiKC0wLjk2OTI2NjAgKiB4ICsgMS44NzYwMTA4ICogeSArIDAuMDQxNTU2MCAqIHopLFxuICAgICAgeHl6MnJnYiggMC4wNTU2NDM0ICogeCAtIDAuMjA0MDI1OSAqIHkgKyAxLjA1NzIyNTIgKiB6KSxcbiAgICAgIHRoaXMub3BhY2l0eVxuICAgICk7XG4gIH1cbn0pKTtcblxuZnVuY3Rpb24geHl6MmxhYih0KSB7XG4gIHJldHVybiB0ID4gdDMgPyBNYXRoLnBvdyh0LCAxIC8gMykgOiB0IC8gdDIgKyB0MDtcbn1cblxuZnVuY3Rpb24gbGFiMnh5eih0KSB7XG4gIHJldHVybiB0ID4gdDEgPyB0ICogdCAqIHQgOiB0MiAqICh0IC0gdDApO1xufVxuXG5mdW5jdGlvbiB4eXoycmdiKHgpIHtcbiAgcmV0dXJuIDI1NSAqICh4IDw9IDAuMDAzMTMwOCA/IDEyLjkyICogeCA6IDEuMDU1ICogTWF0aC5wb3coeCwgMSAvIDIuNCkgLSAwLjA1NSk7XG59XG5cbmZ1bmN0aW9uIHJnYjJ4eXooeCkge1xuICByZXR1cm4gKHggLz0gMjU1KSA8PSAwLjA0MDQ1ID8geCAvIDEyLjkyIDogTWF0aC5wb3coKHggKyAwLjA1NSkgLyAxLjA1NSwgMi40KTtcbn1cblxuZnVuY3Rpb24gaGNsQ29udmVydChvKSB7XG4gIGlmIChvIGluc3RhbmNlb2YgSGNsKSByZXR1cm4gbmV3IEhjbChvLmgsIG8uYywgby5sLCBvLm9wYWNpdHkpO1xuICBpZiAoIShvIGluc3RhbmNlb2YgTGFiKSkgbyA9IGxhYkNvbnZlcnQobyk7XG4gIHZhciBoID0gTWF0aC5hdGFuMihvLmIsIG8uYSkgKiByYWQyZGVnO1xuICByZXR1cm4gbmV3IEhjbChoIDwgMCA/IGggKyAzNjAgOiBoLCBNYXRoLnNxcnQoby5hICogby5hICsgby5iICogby5iKSwgby5sLCBvLm9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBoY2woaCwgYywgbCwgb3BhY2l0eSkge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/IGhjbENvbnZlcnQoaCkgOiBuZXcgSGNsKGgsIGMsIGwsIG9wYWNpdHkgPT0gbnVsbCA/IDEgOiBvcGFjaXR5KTtcbn1cblxuZnVuY3Rpb24gSGNsKGgsIGMsIGwsIG9wYWNpdHkpIHtcbiAgdGhpcy5oID0gK2g7XG4gIHRoaXMuYyA9ICtjO1xuICB0aGlzLmwgPSArbDtcbiAgdGhpcy5vcGFjaXR5ID0gK29wYWNpdHk7XG59XG5cbmRlZmluZShIY2wsIGhjbCwgZXh0ZW5kKENvbG9yLCB7XG4gIGJyaWdodGVyOiBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBIY2wodGhpcy5oLCB0aGlzLmMsIHRoaXMubCArIEtuICogKGsgPT0gbnVsbCA/IDEgOiBrKSwgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgZGFya2VyOiBmdW5jdGlvbihrKSB7XG4gICAgcmV0dXJuIG5ldyBIY2wodGhpcy5oLCB0aGlzLmMsIHRoaXMubCAtIEtuICogKGsgPT0gbnVsbCA/IDEgOiBrKSwgdGhpcy5vcGFjaXR5KTtcbiAgfSxcbiAgcmdiOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbGFiQ29udmVydCh0aGlzKS5yZ2IoKTtcbiAgfVxufSkpO1xuXG52YXIgQSA9IC0wLjE0ODYxO1xudmFyIEIgPSArMS43ODI3NztcbnZhciBDID0gLTAuMjkyMjc7XG52YXIgRCA9IC0wLjkwNjQ5O1xudmFyIEUgPSArMS45NzI5NDtcbnZhciBFRCA9IEUgKiBEO1xudmFyIEVCID0gRSAqIEI7XG52YXIgQkNfREEgPSBCICogQyAtIEQgKiBBO1xuXG5mdW5jdGlvbiBjdWJlaGVsaXhDb252ZXJ0KG8pIHtcbiAgaWYgKG8gaW5zdGFuY2VvZiBDdWJlaGVsaXgpIHJldHVybiBuZXcgQ3ViZWhlbGl4KG8uaCwgby5zLCBvLmwsIG8ub3BhY2l0eSk7XG4gIGlmICghKG8gaW5zdGFuY2VvZiBSZ2IpKSBvID0gcmdiQ29udmVydChvKTtcbiAgdmFyIHIgPSBvLnIgLyAyNTUsXG4gICAgICBnID0gby5nIC8gMjU1LFxuICAgICAgYiA9IG8uYiAvIDI1NSxcbiAgICAgIGwgPSAoQkNfREEgKiBiICsgRUQgKiByIC0gRUIgKiBnKSAvIChCQ19EQSArIEVEIC0gRUIpLFxuICAgICAgYmwgPSBiIC0gbCxcbiAgICAgIGsgPSAoRSAqIChnIC0gbCkgLSBDICogYmwpIC8gRCxcbiAgICAgIHMgPSBNYXRoLnNxcnQoayAqIGsgKyBibCAqIGJsKSAvIChFICogbCAqICgxIC0gbCkpLCAvLyBOYU4gaWYgbD0wIG9yIGw9MVxuICAgICAgaCA9IHMgPyBNYXRoLmF0YW4yKGssIGJsKSAqIHJhZDJkZWcgLSAxMjAgOiBOYU47XG4gIHJldHVybiBuZXcgQ3ViZWhlbGl4KGggPCAwID8gaCArIDM2MCA6IGgsIHMsIGwsIG8ub3BhY2l0eSk7XG59XG5cbmZ1bmN0aW9uIGN1YmVoZWxpeChoLCBzLCBsLCBvcGFjaXR5KSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID09PSAxID8gY3ViZWhlbGl4Q29udmVydChoKSA6IG5ldyBDdWJlaGVsaXgoaCwgcywgbCwgb3BhY2l0eSA9PSBudWxsID8gMSA6IG9wYWNpdHkpO1xufVxuXG5mdW5jdGlvbiBDdWJlaGVsaXgoaCwgcywgbCwgb3BhY2l0eSkge1xuICB0aGlzLmggPSAraDtcbiAgdGhpcy5zID0gK3M7XG4gIHRoaXMubCA9ICtsO1xuICB0aGlzLm9wYWNpdHkgPSArb3BhY2l0eTtcbn1cblxuZGVmaW5lKEN1YmVoZWxpeCwgY3ViZWhlbGl4LCBleHRlbmQoQ29sb3IsIHtcbiAgYnJpZ2h0ZXI6IGZ1bmN0aW9uKGspIHtcbiAgICBrID0gayA9PSBudWxsID8gYnJpZ2h0ZXIgOiBNYXRoLnBvdyhicmlnaHRlciwgayk7XG4gICAgcmV0dXJuIG5ldyBDdWJlaGVsaXgodGhpcy5oLCB0aGlzLnMsIHRoaXMubCAqIGssIHRoaXMub3BhY2l0eSk7XG4gIH0sXG4gIGRhcmtlcjogZnVuY3Rpb24oaykge1xuICAgIGsgPSBrID09IG51bGwgPyBkYXJrZXIgOiBNYXRoLnBvdyhkYXJrZXIsIGspO1xuICAgIHJldHVybiBuZXcgQ3ViZWhlbGl4KHRoaXMuaCwgdGhpcy5zLCB0aGlzLmwgKiBrLCB0aGlzLm9wYWNpdHkpO1xuICB9LFxuICByZ2I6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBoID0gaXNOYU4odGhpcy5oKSA/IDAgOiAodGhpcy5oICsgMTIwKSAqIGRlZzJyYWQsXG4gICAgICAgIGwgPSArdGhpcy5sLFxuICAgICAgICBhID0gaXNOYU4odGhpcy5zKSA/IDAgOiB0aGlzLnMgKiBsICogKDEgLSBsKSxcbiAgICAgICAgY29zaCA9IE1hdGguY29zKGgpLFxuICAgICAgICBzaW5oID0gTWF0aC5zaW4oaCk7XG4gICAgcmV0dXJuIG5ldyBSZ2IoXG4gICAgICAyNTUgKiAobCArIGEgKiAoQSAqIGNvc2ggKyBCICogc2luaCkpLFxuICAgICAgMjU1ICogKGwgKyBhICogKEMgKiBjb3NoICsgRCAqIHNpbmgpKSxcbiAgICAgIDI1NSAqIChsICsgYSAqIChFICogY29zaCkpLFxuICAgICAgdGhpcy5vcGFjaXR5XG4gICAgKTtcbiAgfVxufSkpO1xuXG5leHBvcnRzLmNvbG9yID0gY29sb3I7XG5leHBvcnRzLnJnYiA9IHJnYjtcbmV4cG9ydHMuaHNsID0gaHNsO1xuZXhwb3J0cy5sYWIgPSBsYWI7XG5leHBvcnRzLmhjbCA9IGhjbDtcbmV4cG9ydHMuY3ViZWhlbGl4ID0gY3ViZWhlbGl4O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1kaXNwYXRjaC8gVmVyc2lvbiAxLjAuMy4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgbm9vcCA9IHt2YWx1ZTogZnVuY3Rpb24oKSB7fX07XG5cbmZ1bmN0aW9uIGRpc3BhdGNoKCkge1xuICBmb3IgKHZhciBpID0gMCwgbiA9IGFyZ3VtZW50cy5sZW5ndGgsIF8gPSB7fSwgdDsgaSA8IG47ICsraSkge1xuICAgIGlmICghKHQgPSBhcmd1bWVudHNbaV0gKyBcIlwiKSB8fCAodCBpbiBfKSkgdGhyb3cgbmV3IEVycm9yKFwiaWxsZWdhbCB0eXBlOiBcIiArIHQpO1xuICAgIF9bdF0gPSBbXTtcbiAgfVxuICByZXR1cm4gbmV3IERpc3BhdGNoKF8pO1xufVxuXG5mdW5jdGlvbiBEaXNwYXRjaChfKSB7XG4gIHRoaXMuXyA9IF87XG59XG5cbmZ1bmN0aW9uIHBhcnNlVHlwZW5hbWVzKHR5cGVuYW1lcywgdHlwZXMpIHtcbiAgcmV0dXJuIHR5cGVuYW1lcy50cmltKCkuc3BsaXQoL158XFxzKy8pLm1hcChmdW5jdGlvbih0KSB7XG4gICAgdmFyIG5hbWUgPSBcIlwiLCBpID0gdC5pbmRleE9mKFwiLlwiKTtcbiAgICBpZiAoaSA+PSAwKSBuYW1lID0gdC5zbGljZShpICsgMSksIHQgPSB0LnNsaWNlKDAsIGkpO1xuICAgIGlmICh0ICYmICF0eXBlcy5oYXNPd25Qcm9wZXJ0eSh0KSkgdGhyb3cgbmV3IEVycm9yKFwidW5rbm93biB0eXBlOiBcIiArIHQpO1xuICAgIHJldHVybiB7dHlwZTogdCwgbmFtZTogbmFtZX07XG4gIH0pO1xufVxuXG5EaXNwYXRjaC5wcm90b3R5cGUgPSBkaXNwYXRjaC5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBEaXNwYXRjaCxcbiAgb246IGZ1bmN0aW9uKHR5cGVuYW1lLCBjYWxsYmFjaykge1xuICAgIHZhciBfID0gdGhpcy5fLFxuICAgICAgICBUID0gcGFyc2VUeXBlbmFtZXModHlwZW5hbWUgKyBcIlwiLCBfKSxcbiAgICAgICAgdCxcbiAgICAgICAgaSA9IC0xLFxuICAgICAgICBuID0gVC5sZW5ndGg7XG5cbiAgICAvLyBJZiBubyBjYWxsYmFjayB3YXMgc3BlY2lmaWVkLCByZXR1cm4gdGhlIGNhbGxiYWNrIG9mIHRoZSBnaXZlbiB0eXBlIGFuZCBuYW1lLlxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikge1xuICAgICAgd2hpbGUgKCsraSA8IG4pIGlmICgodCA9ICh0eXBlbmFtZSA9IFRbaV0pLnR5cGUpICYmICh0ID0gZ2V0KF9bdF0sIHR5cGVuYW1lLm5hbWUpKSkgcmV0dXJuIHQ7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgYSB0eXBlIHdhcyBzcGVjaWZpZWQsIHNldCB0aGUgY2FsbGJhY2sgZm9yIHRoZSBnaXZlbiB0eXBlIGFuZCBuYW1lLlxuICAgIC8vIE90aGVyd2lzZSwgaWYgYSBudWxsIGNhbGxiYWNrIHdhcyBzcGVjaWZpZWQsIHJlbW92ZSBjYWxsYmFja3Mgb2YgdGhlIGdpdmVuIG5hbWUuXG4gICAgaWYgKGNhbGxiYWNrICE9IG51bGwgJiYgdHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgY2FsbGJhY2s6IFwiICsgY2FsbGJhY2spO1xuICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICBpZiAodCA9ICh0eXBlbmFtZSA9IFRbaV0pLnR5cGUpIF9bdF0gPSBzZXQoX1t0XSwgdHlwZW5hbWUubmFtZSwgY2FsbGJhY2spO1xuICAgICAgZWxzZSBpZiAoY2FsbGJhY2sgPT0gbnVsbCkgZm9yICh0IGluIF8pIF9bdF0gPSBzZXQoX1t0XSwgdHlwZW5hbWUubmFtZSwgbnVsbCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIGNvcHk6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBjb3B5ID0ge30sIF8gPSB0aGlzLl87XG4gICAgZm9yICh2YXIgdCBpbiBfKSBjb3B5W3RdID0gX1t0XS5zbGljZSgpO1xuICAgIHJldHVybiBuZXcgRGlzcGF0Y2goY29weSk7XG4gIH0sXG4gIGNhbGw6IGZ1bmN0aW9uKHR5cGUsIHRoYXQpIHtcbiAgICBpZiAoKG4gPSBhcmd1bWVudHMubGVuZ3RoIC0gMikgPiAwKSBmb3IgKHZhciBhcmdzID0gbmV3IEFycmF5KG4pLCBpID0gMCwgbiwgdDsgaSA8IG47ICsraSkgYXJnc1tpXSA9IGFyZ3VtZW50c1tpICsgMl07XG4gICAgaWYgKCF0aGlzLl8uaGFzT3duUHJvcGVydHkodHlwZSkpIHRocm93IG5ldyBFcnJvcihcInVua25vd24gdHlwZTogXCIgKyB0eXBlKTtcbiAgICBmb3IgKHQgPSB0aGlzLl9bdHlwZV0sIGkgPSAwLCBuID0gdC5sZW5ndGg7IGkgPCBuOyArK2kpIHRbaV0udmFsdWUuYXBwbHkodGhhdCwgYXJncyk7XG4gIH0sXG4gIGFwcGx5OiBmdW5jdGlvbih0eXBlLCB0aGF0LCBhcmdzKSB7XG4gICAgaWYgKCF0aGlzLl8uaGFzT3duUHJvcGVydHkodHlwZSkpIHRocm93IG5ldyBFcnJvcihcInVua25vd24gdHlwZTogXCIgKyB0eXBlKTtcbiAgICBmb3IgKHZhciB0ID0gdGhpcy5fW3R5cGVdLCBpID0gMCwgbiA9IHQubGVuZ3RoOyBpIDwgbjsgKytpKSB0W2ldLnZhbHVlLmFwcGx5KHRoYXQsIGFyZ3MpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBnZXQodHlwZSwgbmFtZSkge1xuICBmb3IgKHZhciBpID0gMCwgbiA9IHR5cGUubGVuZ3RoLCBjOyBpIDwgbjsgKytpKSB7XG4gICAgaWYgKChjID0gdHlwZVtpXSkubmFtZSA9PT0gbmFtZSkge1xuICAgICAgcmV0dXJuIGMudmFsdWU7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIHNldCh0eXBlLCBuYW1lLCBjYWxsYmFjaykge1xuICBmb3IgKHZhciBpID0gMCwgbiA9IHR5cGUubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgaWYgKHR5cGVbaV0ubmFtZSA9PT0gbmFtZSkge1xuICAgICAgdHlwZVtpXSA9IG5vb3AsIHR5cGUgPSB0eXBlLnNsaWNlKDAsIGkpLmNvbmNhdCh0eXBlLnNsaWNlKGkgKyAxKSk7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgaWYgKGNhbGxiYWNrICE9IG51bGwpIHR5cGUucHVzaCh7bmFtZTogbmFtZSwgdmFsdWU6IGNhbGxiYWNrfSk7XG4gIHJldHVybiB0eXBlO1xufVxuXG5leHBvcnRzLmRpc3BhdGNoID0gZGlzcGF0Y2g7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWRyYWcvIFZlcnNpb24gMS4yLjEuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgcmVxdWlyZSgnZDMtZGlzcGF0Y2gnKSwgcmVxdWlyZSgnZDMtc2VsZWN0aW9uJykpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cycsICdkMy1kaXNwYXRjaCcsICdkMy1zZWxlY3Rpb24nXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMsZ2xvYmFsLmQzKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cyxkM0Rpc3BhdGNoLGQzU2VsZWN0aW9uKSB7ICd1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gbm9wcm9wYWdhdGlvbigpIHtcbiAgZDNTZWxlY3Rpb24uZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG59XG5cbnZhciBub2V2ZW50ID0gZnVuY3Rpb24oKSB7XG4gIGQzU2VsZWN0aW9uLmV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIGQzU2VsZWN0aW9uLmV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xufTtcblxudmFyIG5vZHJhZyA9IGZ1bmN0aW9uKHZpZXcpIHtcbiAgdmFyIHJvb3QgPSB2aWV3LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCxcbiAgICAgIHNlbGVjdGlvbiA9IGQzU2VsZWN0aW9uLnNlbGVjdCh2aWV3KS5vbihcImRyYWdzdGFydC5kcmFnXCIsIG5vZXZlbnQsIHRydWUpO1xuICBpZiAoXCJvbnNlbGVjdHN0YXJ0XCIgaW4gcm9vdCkge1xuICAgIHNlbGVjdGlvbi5vbihcInNlbGVjdHN0YXJ0LmRyYWdcIiwgbm9ldmVudCwgdHJ1ZSk7XG4gIH0gZWxzZSB7XG4gICAgcm9vdC5fX25vc2VsZWN0ID0gcm9vdC5zdHlsZS5Nb3pVc2VyU2VsZWN0O1xuICAgIHJvb3Quc3R5bGUuTW96VXNlclNlbGVjdCA9IFwibm9uZVwiO1xuICB9XG59O1xuXG5mdW5jdGlvbiB5ZXNkcmFnKHZpZXcsIG5vY2xpY2spIHtcbiAgdmFyIHJvb3QgPSB2aWV3LmRvY3VtZW50LmRvY3VtZW50RWxlbWVudCxcbiAgICAgIHNlbGVjdGlvbiA9IGQzU2VsZWN0aW9uLnNlbGVjdCh2aWV3KS5vbihcImRyYWdzdGFydC5kcmFnXCIsIG51bGwpO1xuICBpZiAobm9jbGljaykge1xuICAgIHNlbGVjdGlvbi5vbihcImNsaWNrLmRyYWdcIiwgbm9ldmVudCwgdHJ1ZSk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgc2VsZWN0aW9uLm9uKFwiY2xpY2suZHJhZ1wiLCBudWxsKTsgfSwgMCk7XG4gIH1cbiAgaWYgKFwib25zZWxlY3RzdGFydFwiIGluIHJvb3QpIHtcbiAgICBzZWxlY3Rpb24ub24oXCJzZWxlY3RzdGFydC5kcmFnXCIsIG51bGwpO1xuICB9IGVsc2Uge1xuICAgIHJvb3Quc3R5bGUuTW96VXNlclNlbGVjdCA9IHJvb3QuX19ub3NlbGVjdDtcbiAgICBkZWxldGUgcm9vdC5fX25vc2VsZWN0O1xuICB9XG59XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxuZnVuY3Rpb24gRHJhZ0V2ZW50KHRhcmdldCwgdHlwZSwgc3ViamVjdCwgaWQsIGFjdGl2ZSwgeCwgeSwgZHgsIGR5LCBkaXNwYXRjaCQkMSkge1xuICB0aGlzLnRhcmdldCA9IHRhcmdldDtcbiAgdGhpcy50eXBlID0gdHlwZTtcbiAgdGhpcy5zdWJqZWN0ID0gc3ViamVjdDtcbiAgdGhpcy5pZGVudGlmaWVyID0gaWQ7XG4gIHRoaXMuYWN0aXZlID0gYWN0aXZlO1xuICB0aGlzLnggPSB4O1xuICB0aGlzLnkgPSB5O1xuICB0aGlzLmR4ID0gZHg7XG4gIHRoaXMuZHkgPSBkeTtcbiAgdGhpcy5fID0gZGlzcGF0Y2gkJDE7XG59XG5cbkRyYWdFdmVudC5wcm90b3R5cGUub24gPSBmdW5jdGlvbigpIHtcbiAgdmFyIHZhbHVlID0gdGhpcy5fLm9uLmFwcGx5KHRoaXMuXywgYXJndW1lbnRzKTtcbiAgcmV0dXJuIHZhbHVlID09PSB0aGlzLl8gPyB0aGlzIDogdmFsdWU7XG59O1xuXG4vLyBJZ25vcmUgcmlnaHQtY2xpY2ssIHNpbmNlIHRoYXQgc2hvdWxkIG9wZW4gdGhlIGNvbnRleHQgbWVudS5cbmZ1bmN0aW9uIGRlZmF1bHRGaWx0ZXIoKSB7XG4gIHJldHVybiAhZDNTZWxlY3Rpb24uZXZlbnQuYnV0dG9uO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0Q29udGFpbmVyKCkge1xuICByZXR1cm4gdGhpcy5wYXJlbnROb2RlO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0U3ViamVjdChkKSB7XG4gIHJldHVybiBkID09IG51bGwgPyB7eDogZDNTZWxlY3Rpb24uZXZlbnQueCwgeTogZDNTZWxlY3Rpb24uZXZlbnQueX0gOiBkO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0VG91Y2hhYmxlKCkge1xuICByZXR1cm4gXCJvbnRvdWNoc3RhcnRcIiBpbiB0aGlzO1xufVxuXG52YXIgZHJhZyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZmlsdGVyID0gZGVmYXVsdEZpbHRlcixcbiAgICAgIGNvbnRhaW5lciA9IGRlZmF1bHRDb250YWluZXIsXG4gICAgICBzdWJqZWN0ID0gZGVmYXVsdFN1YmplY3QsXG4gICAgICB0b3VjaGFibGUgPSBkZWZhdWx0VG91Y2hhYmxlLFxuICAgICAgZ2VzdHVyZXMgPSB7fSxcbiAgICAgIGxpc3RlbmVycyA9IGQzRGlzcGF0Y2guZGlzcGF0Y2goXCJzdGFydFwiLCBcImRyYWdcIiwgXCJlbmRcIiksXG4gICAgICBhY3RpdmUgPSAwLFxuICAgICAgbW91c2Vkb3dueCxcbiAgICAgIG1vdXNlZG93bnksXG4gICAgICBtb3VzZW1vdmluZyxcbiAgICAgIHRvdWNoZW5kaW5nLFxuICAgICAgY2xpY2tEaXN0YW5jZTIgPSAwO1xuXG4gIGZ1bmN0aW9uIGRyYWcoc2VsZWN0aW9uKSB7XG4gICAgc2VsZWN0aW9uXG4gICAgICAgIC5vbihcIm1vdXNlZG93bi5kcmFnXCIsIG1vdXNlZG93bmVkKVxuICAgICAgLmZpbHRlcih0b3VjaGFibGUpXG4gICAgICAgIC5vbihcInRvdWNoc3RhcnQuZHJhZ1wiLCB0b3VjaHN0YXJ0ZWQpXG4gICAgICAgIC5vbihcInRvdWNobW92ZS5kcmFnXCIsIHRvdWNobW92ZWQpXG4gICAgICAgIC5vbihcInRvdWNoZW5kLmRyYWcgdG91Y2hjYW5jZWwuZHJhZ1wiLCB0b3VjaGVuZGVkKVxuICAgICAgICAuc3R5bGUoXCJ0b3VjaC1hY3Rpb25cIiwgXCJub25lXCIpXG4gICAgICAgIC5zdHlsZShcIi13ZWJraXQtdGFwLWhpZ2hsaWdodC1jb2xvclwiLCBcInJnYmEoMCwwLDAsMClcIik7XG4gIH1cblxuICBmdW5jdGlvbiBtb3VzZWRvd25lZCgpIHtcbiAgICBpZiAodG91Y2hlbmRpbmcgfHwgIWZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSByZXR1cm47XG4gICAgdmFyIGdlc3R1cmUgPSBiZWZvcmVzdGFydChcIm1vdXNlXCIsIGNvbnRhaW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCBkM1NlbGVjdGlvbi5tb3VzZSwgdGhpcywgYXJndW1lbnRzKTtcbiAgICBpZiAoIWdlc3R1cmUpIHJldHVybjtcbiAgICBkM1NlbGVjdGlvbi5zZWxlY3QoZDNTZWxlY3Rpb24uZXZlbnQudmlldykub24oXCJtb3VzZW1vdmUuZHJhZ1wiLCBtb3VzZW1vdmVkLCB0cnVlKS5vbihcIm1vdXNldXAuZHJhZ1wiLCBtb3VzZXVwcGVkLCB0cnVlKTtcbiAgICBub2RyYWcoZDNTZWxlY3Rpb24uZXZlbnQudmlldyk7XG4gICAgbm9wcm9wYWdhdGlvbigpO1xuICAgIG1vdXNlbW92aW5nID0gZmFsc2U7XG4gICAgbW91c2Vkb3dueCA9IGQzU2VsZWN0aW9uLmV2ZW50LmNsaWVudFg7XG4gICAgbW91c2Vkb3dueSA9IGQzU2VsZWN0aW9uLmV2ZW50LmNsaWVudFk7XG4gICAgZ2VzdHVyZShcInN0YXJ0XCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gbW91c2Vtb3ZlZCgpIHtcbiAgICBub2V2ZW50KCk7XG4gICAgaWYgKCFtb3VzZW1vdmluZykge1xuICAgICAgdmFyIGR4ID0gZDNTZWxlY3Rpb24uZXZlbnQuY2xpZW50WCAtIG1vdXNlZG93bngsIGR5ID0gZDNTZWxlY3Rpb24uZXZlbnQuY2xpZW50WSAtIG1vdXNlZG93bnk7XG4gICAgICBtb3VzZW1vdmluZyA9IGR4ICogZHggKyBkeSAqIGR5ID4gY2xpY2tEaXN0YW5jZTI7XG4gICAgfVxuICAgIGdlc3R1cmVzLm1vdXNlKFwiZHJhZ1wiKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1vdXNldXBwZWQoKSB7XG4gICAgZDNTZWxlY3Rpb24uc2VsZWN0KGQzU2VsZWN0aW9uLmV2ZW50LnZpZXcpLm9uKFwibW91c2Vtb3ZlLmRyYWcgbW91c2V1cC5kcmFnXCIsIG51bGwpO1xuICAgIHllc2RyYWcoZDNTZWxlY3Rpb24uZXZlbnQudmlldywgbW91c2Vtb3ZpbmcpO1xuICAgIG5vZXZlbnQoKTtcbiAgICBnZXN0dXJlcy5tb3VzZShcImVuZFwiKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRvdWNoc3RhcnRlZCgpIHtcbiAgICBpZiAoIWZpbHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSByZXR1cm47XG4gICAgdmFyIHRvdWNoZXMgPSBkM1NlbGVjdGlvbi5ldmVudC5jaGFuZ2VkVG91Y2hlcyxcbiAgICAgICAgYyA9IGNvbnRhaW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpLFxuICAgICAgICBuID0gdG91Y2hlcy5sZW5ndGgsIGksIGdlc3R1cmU7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoZ2VzdHVyZSA9IGJlZm9yZXN0YXJ0KHRvdWNoZXNbaV0uaWRlbnRpZmllciwgYywgZDNTZWxlY3Rpb24udG91Y2gsIHRoaXMsIGFyZ3VtZW50cykpIHtcbiAgICAgICAgbm9wcm9wYWdhdGlvbigpO1xuICAgICAgICBnZXN0dXJlKFwic3RhcnRcIik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gdG91Y2htb3ZlZCgpIHtcbiAgICB2YXIgdG91Y2hlcyA9IGQzU2VsZWN0aW9uLmV2ZW50LmNoYW5nZWRUb3VjaGVzLFxuICAgICAgICBuID0gdG91Y2hlcy5sZW5ndGgsIGksIGdlc3R1cmU7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoZ2VzdHVyZSA9IGdlc3R1cmVzW3RvdWNoZXNbaV0uaWRlbnRpZmllcl0pIHtcbiAgICAgICAgbm9ldmVudCgpO1xuICAgICAgICBnZXN0dXJlKFwiZHJhZ1wiKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiB0b3VjaGVuZGVkKCkge1xuICAgIHZhciB0b3VjaGVzID0gZDNTZWxlY3Rpb24uZXZlbnQuY2hhbmdlZFRvdWNoZXMsXG4gICAgICAgIG4gPSB0b3VjaGVzLmxlbmd0aCwgaSwgZ2VzdHVyZTtcblxuICAgIGlmICh0b3VjaGVuZGluZykgY2xlYXJUaW1lb3V0KHRvdWNoZW5kaW5nKTtcbiAgICB0b3VjaGVuZGluZyA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IHRvdWNoZW5kaW5nID0gbnVsbDsgfSwgNTAwKTsgLy8gR2hvc3QgY2xpY2tzIGFyZSBkZWxheWVkIVxuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGlmIChnZXN0dXJlID0gZ2VzdHVyZXNbdG91Y2hlc1tpXS5pZGVudGlmaWVyXSkge1xuICAgICAgICBub3Byb3BhZ2F0aW9uKCk7XG4gICAgICAgIGdlc3R1cmUoXCJlbmRcIik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gYmVmb3Jlc3RhcnQoaWQsIGNvbnRhaW5lciwgcG9pbnQsIHRoYXQsIGFyZ3MpIHtcbiAgICB2YXIgcCA9IHBvaW50KGNvbnRhaW5lciwgaWQpLCBzLCBkeCwgZHksXG4gICAgICAgIHN1Ymxpc3RlbmVycyA9IGxpc3RlbmVycy5jb3B5KCk7XG5cbiAgICBpZiAoIWQzU2VsZWN0aW9uLmN1c3RvbUV2ZW50KG5ldyBEcmFnRXZlbnQoZHJhZywgXCJiZWZvcmVzdGFydFwiLCBzLCBpZCwgYWN0aXZlLCBwWzBdLCBwWzFdLCAwLCAwLCBzdWJsaXN0ZW5lcnMpLCBmdW5jdGlvbigpIHtcbiAgICAgIGlmICgoZDNTZWxlY3Rpb24uZXZlbnQuc3ViamVjdCA9IHMgPSBzdWJqZWN0LmFwcGx5KHRoYXQsIGFyZ3MpKSA9PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gICAgICBkeCA9IHMueCAtIHBbMF0gfHwgMDtcbiAgICAgIGR5ID0gcy55IC0gcFsxXSB8fCAwO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSkpIHJldHVybjtcblxuICAgIHJldHVybiBmdW5jdGlvbiBnZXN0dXJlKHR5cGUpIHtcbiAgICAgIHZhciBwMCA9IHAsIG47XG4gICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSBcInN0YXJ0XCI6IGdlc3R1cmVzW2lkXSA9IGdlc3R1cmUsIG4gPSBhY3RpdmUrKzsgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJlbmRcIjogZGVsZXRlIGdlc3R1cmVzW2lkXSwgLS1hY3RpdmU7IC8vIG5vYnJlYWtcbiAgICAgICAgY2FzZSBcImRyYWdcIjogcCA9IHBvaW50KGNvbnRhaW5lciwgaWQpLCBuID0gYWN0aXZlOyBicmVhaztcbiAgICAgIH1cbiAgICAgIGQzU2VsZWN0aW9uLmN1c3RvbUV2ZW50KG5ldyBEcmFnRXZlbnQoZHJhZywgdHlwZSwgcywgaWQsIG4sIHBbMF0gKyBkeCwgcFsxXSArIGR5LCBwWzBdIC0gcDBbMF0sIHBbMV0gLSBwMFsxXSwgc3VibGlzdGVuZXJzKSwgc3VibGlzdGVuZXJzLmFwcGx5LCBzdWJsaXN0ZW5lcnMsIFt0eXBlLCB0aGF0LCBhcmdzXSk7XG4gICAgfTtcbiAgfVxuXG4gIGRyYWcuZmlsdGVyID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGZpbHRlciA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoISFfKSwgZHJhZykgOiBmaWx0ZXI7XG4gIH07XG5cbiAgZHJhZy5jb250YWluZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY29udGFpbmVyID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChfKSwgZHJhZykgOiBjb250YWluZXI7XG4gIH07XG5cbiAgZHJhZy5zdWJqZWN0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN1YmplY3QgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KF8pLCBkcmFnKSA6IHN1YmplY3Q7XG4gIH07XG5cbiAgZHJhZy50b3VjaGFibGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodG91Y2hhYmxlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCghIV8pLCBkcmFnKSA6IHRvdWNoYWJsZTtcbiAgfTtcblxuICBkcmFnLm9uID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZhbHVlID0gbGlzdGVuZXJzLm9uLmFwcGx5KGxpc3RlbmVycywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gdmFsdWUgPT09IGxpc3RlbmVycyA/IGRyYWcgOiB2YWx1ZTtcbiAgfTtcblxuICBkcmFnLmNsaWNrRGlzdGFuY2UgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2xpY2tEaXN0YW5jZTIgPSAoXyA9ICtfKSAqIF8sIGRyYWcpIDogTWF0aC5zcXJ0KGNsaWNrRGlzdGFuY2UyKTtcbiAgfTtcblxuICByZXR1cm4gZHJhZztcbn07XG5cbmV4cG9ydHMuZHJhZyA9IGRyYWc7XG5leHBvcnRzLmRyYWdEaXNhYmxlID0gbm9kcmFnO1xuZXhwb3J0cy5kcmFnRW5hYmxlID0geWVzZHJhZztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtZHN2LyBWZXJzaW9uIDEuMC44LiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBFT0wgPSB7fTtcbnZhciBFT0YgPSB7fTtcbnZhciBRVU9URSA9IDM0O1xudmFyIE5FV0xJTkUgPSAxMDtcbnZhciBSRVRVUk4gPSAxMztcblxuZnVuY3Rpb24gb2JqZWN0Q29udmVydGVyKGNvbHVtbnMpIHtcbiAgcmV0dXJuIG5ldyBGdW5jdGlvbihcImRcIiwgXCJyZXR1cm4ge1wiICsgY29sdW1ucy5tYXAoZnVuY3Rpb24obmFtZSwgaSkge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShuYW1lKSArIFwiOiBkW1wiICsgaSArIFwiXVwiO1xuICB9KS5qb2luKFwiLFwiKSArIFwifVwiKTtcbn1cblxuZnVuY3Rpb24gY3VzdG9tQ29udmVydGVyKGNvbHVtbnMsIGYpIHtcbiAgdmFyIG9iamVjdCA9IG9iamVjdENvbnZlcnRlcihjb2x1bW5zKTtcbiAgcmV0dXJuIGZ1bmN0aW9uKHJvdywgaSkge1xuICAgIHJldHVybiBmKG9iamVjdChyb3cpLCBpLCBjb2x1bW5zKTtcbiAgfTtcbn1cblxuLy8gQ29tcHV0ZSB1bmlxdWUgY29sdW1ucyBpbiBvcmRlciBvZiBkaXNjb3ZlcnkuXG5mdW5jdGlvbiBpbmZlckNvbHVtbnMocm93cykge1xuICB2YXIgY29sdW1uU2V0ID0gT2JqZWN0LmNyZWF0ZShudWxsKSxcbiAgICAgIGNvbHVtbnMgPSBbXTtcblxuICByb3dzLmZvckVhY2goZnVuY3Rpb24ocm93KSB7XG4gICAgZm9yICh2YXIgY29sdW1uIGluIHJvdykge1xuICAgICAgaWYgKCEoY29sdW1uIGluIGNvbHVtblNldCkpIHtcbiAgICAgICAgY29sdW1ucy5wdXNoKGNvbHVtblNldFtjb2x1bW5dID0gY29sdW1uKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBjb2x1bW5zO1xufVxuXG52YXIgZHN2ID0gZnVuY3Rpb24oZGVsaW1pdGVyKSB7XG4gIHZhciByZUZvcm1hdCA9IG5ldyBSZWdFeHAoXCJbXFxcIlwiICsgZGVsaW1pdGVyICsgXCJcXG5cXHJdXCIpLFxuICAgICAgREVMSU1JVEVSID0gZGVsaW1pdGVyLmNoYXJDb2RlQXQoMCk7XG5cbiAgZnVuY3Rpb24gcGFyc2UodGV4dCwgZikge1xuICAgIHZhciBjb252ZXJ0LCBjb2x1bW5zLCByb3dzID0gcGFyc2VSb3dzKHRleHQsIGZ1bmN0aW9uKHJvdywgaSkge1xuICAgICAgaWYgKGNvbnZlcnQpIHJldHVybiBjb252ZXJ0KHJvdywgaSAtIDEpO1xuICAgICAgY29sdW1ucyA9IHJvdywgY29udmVydCA9IGYgPyBjdXN0b21Db252ZXJ0ZXIocm93LCBmKSA6IG9iamVjdENvbnZlcnRlcihyb3cpO1xuICAgIH0pO1xuICAgIHJvd3MuY29sdW1ucyA9IGNvbHVtbnMgfHwgW107XG4gICAgcmV0dXJuIHJvd3M7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVJvd3ModGV4dCwgZikge1xuICAgIHZhciByb3dzID0gW10sIC8vIG91dHB1dCByb3dzXG4gICAgICAgIE4gPSB0ZXh0Lmxlbmd0aCxcbiAgICAgICAgSSA9IDAsIC8vIGN1cnJlbnQgY2hhcmFjdGVyIGluZGV4XG4gICAgICAgIG4gPSAwLCAvLyBjdXJyZW50IGxpbmUgbnVtYmVyXG4gICAgICAgIHQsIC8vIGN1cnJlbnQgdG9rZW5cbiAgICAgICAgZW9mID0gTiA8PSAwLCAvLyBjdXJyZW50IHRva2VuIGZvbGxvd2VkIGJ5IEVPRj9cbiAgICAgICAgZW9sID0gZmFsc2U7IC8vIGN1cnJlbnQgdG9rZW4gZm9sbG93ZWQgYnkgRU9MP1xuXG4gICAgLy8gU3RyaXAgdGhlIHRyYWlsaW5nIG5ld2xpbmUuXG4gICAgaWYgKHRleHQuY2hhckNvZGVBdChOIC0gMSkgPT09IE5FV0xJTkUpIC0tTjtcbiAgICBpZiAodGV4dC5jaGFyQ29kZUF0KE4gLSAxKSA9PT0gUkVUVVJOKSAtLU47XG5cbiAgICBmdW5jdGlvbiB0b2tlbigpIHtcbiAgICAgIGlmIChlb2YpIHJldHVybiBFT0Y7XG4gICAgICBpZiAoZW9sKSByZXR1cm4gZW9sID0gZmFsc2UsIEVPTDtcblxuICAgICAgLy8gVW5lc2NhcGUgcXVvdGVzLlxuICAgICAgdmFyIGksIGogPSBJLCBjO1xuICAgICAgaWYgKHRleHQuY2hhckNvZGVBdChqKSA9PT0gUVVPVEUpIHtcbiAgICAgICAgd2hpbGUgKEkrKyA8IE4gJiYgdGV4dC5jaGFyQ29kZUF0KEkpICE9PSBRVU9URSB8fCB0ZXh0LmNoYXJDb2RlQXQoKytJKSA9PT0gUVVPVEUpO1xuICAgICAgICBpZiAoKGkgPSBJKSA+PSBOKSBlb2YgPSB0cnVlO1xuICAgICAgICBlbHNlIGlmICgoYyA9IHRleHQuY2hhckNvZGVBdChJKyspKSA9PT0gTkVXTElORSkgZW9sID0gdHJ1ZTtcbiAgICAgICAgZWxzZSBpZiAoYyA9PT0gUkVUVVJOKSB7IGVvbCA9IHRydWU7IGlmICh0ZXh0LmNoYXJDb2RlQXQoSSkgPT09IE5FV0xJTkUpICsrSTsgfVxuICAgICAgICByZXR1cm4gdGV4dC5zbGljZShqICsgMSwgaSAtIDEpLnJlcGxhY2UoL1wiXCIvZywgXCJcXFwiXCIpO1xuICAgICAgfVxuXG4gICAgICAvLyBGaW5kIG5leHQgZGVsaW1pdGVyIG9yIG5ld2xpbmUuXG4gICAgICB3aGlsZSAoSSA8IE4pIHtcbiAgICAgICAgaWYgKChjID0gdGV4dC5jaGFyQ29kZUF0KGkgPSBJKyspKSA9PT0gTkVXTElORSkgZW9sID0gdHJ1ZTtcbiAgICAgICAgZWxzZSBpZiAoYyA9PT0gUkVUVVJOKSB7IGVvbCA9IHRydWU7IGlmICh0ZXh0LmNoYXJDb2RlQXQoSSkgPT09IE5FV0xJTkUpICsrSTsgfVxuICAgICAgICBlbHNlIGlmIChjICE9PSBERUxJTUlURVIpIGNvbnRpbnVlO1xuICAgICAgICByZXR1cm4gdGV4dC5zbGljZShqLCBpKTtcbiAgICAgIH1cblxuICAgICAgLy8gUmV0dXJuIGxhc3QgdG9rZW4gYmVmb3JlIEVPRi5cbiAgICAgIHJldHVybiBlb2YgPSB0cnVlLCB0ZXh0LnNsaWNlKGosIE4pO1xuICAgIH1cblxuICAgIHdoaWxlICgodCA9IHRva2VuKCkpICE9PSBFT0YpIHtcbiAgICAgIHZhciByb3cgPSBbXTtcbiAgICAgIHdoaWxlICh0ICE9PSBFT0wgJiYgdCAhPT0gRU9GKSByb3cucHVzaCh0KSwgdCA9IHRva2VuKCk7XG4gICAgICBpZiAoZiAmJiAocm93ID0gZihyb3csIG4rKykpID09IG51bGwpIGNvbnRpbnVlO1xuICAgICAgcm93cy5wdXNoKHJvdyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvd3M7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXQocm93cywgY29sdW1ucykge1xuICAgIGlmIChjb2x1bW5zID09IG51bGwpIGNvbHVtbnMgPSBpbmZlckNvbHVtbnMocm93cyk7XG4gICAgcmV0dXJuIFtjb2x1bW5zLm1hcChmb3JtYXRWYWx1ZSkuam9pbihkZWxpbWl0ZXIpXS5jb25jYXQocm93cy5tYXAoZnVuY3Rpb24ocm93KSB7XG4gICAgICByZXR1cm4gY29sdW1ucy5tYXAoZnVuY3Rpb24oY29sdW1uKSB7XG4gICAgICAgIHJldHVybiBmb3JtYXRWYWx1ZShyb3dbY29sdW1uXSk7XG4gICAgICB9KS5qb2luKGRlbGltaXRlcik7XG4gICAgfSkpLmpvaW4oXCJcXG5cIik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRSb3dzKHJvd3MpIHtcbiAgICByZXR1cm4gcm93cy5tYXAoZm9ybWF0Um93KS5qb2luKFwiXFxuXCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0Um93KHJvdykge1xuICAgIHJldHVybiByb3cubWFwKGZvcm1hdFZhbHVlKS5qb2luKGRlbGltaXRlcik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRWYWx1ZSh0ZXh0KSB7XG4gICAgcmV0dXJuIHRleHQgPT0gbnVsbCA/IFwiXCJcbiAgICAgICAgOiByZUZvcm1hdC50ZXN0KHRleHQgKz0gXCJcIikgPyBcIlxcXCJcIiArIHRleHQucmVwbGFjZSgvXCIvZywgXCJcXFwiXFxcIlwiKSArIFwiXFxcIlwiXG4gICAgICAgIDogdGV4dDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcGFyc2U6IHBhcnNlLFxuICAgIHBhcnNlUm93czogcGFyc2VSb3dzLFxuICAgIGZvcm1hdDogZm9ybWF0LFxuICAgIGZvcm1hdFJvd3M6IGZvcm1hdFJvd3NcbiAgfTtcbn07XG5cbnZhciBjc3YgPSBkc3YoXCIsXCIpO1xuXG52YXIgY3N2UGFyc2UgPSBjc3YucGFyc2U7XG52YXIgY3N2UGFyc2VSb3dzID0gY3N2LnBhcnNlUm93cztcbnZhciBjc3ZGb3JtYXQgPSBjc3YuZm9ybWF0O1xudmFyIGNzdkZvcm1hdFJvd3MgPSBjc3YuZm9ybWF0Um93cztcblxudmFyIHRzdiA9IGRzdihcIlxcdFwiKTtcblxudmFyIHRzdlBhcnNlID0gdHN2LnBhcnNlO1xudmFyIHRzdlBhcnNlUm93cyA9IHRzdi5wYXJzZVJvd3M7XG52YXIgdHN2Rm9ybWF0ID0gdHN2LmZvcm1hdDtcbnZhciB0c3ZGb3JtYXRSb3dzID0gdHN2LmZvcm1hdFJvd3M7XG5cbmV4cG9ydHMuZHN2Rm9ybWF0ID0gZHN2O1xuZXhwb3J0cy5jc3ZQYXJzZSA9IGNzdlBhcnNlO1xuZXhwb3J0cy5jc3ZQYXJzZVJvd3MgPSBjc3ZQYXJzZVJvd3M7XG5leHBvcnRzLmNzdkZvcm1hdCA9IGNzdkZvcm1hdDtcbmV4cG9ydHMuY3N2Rm9ybWF0Um93cyA9IGNzdkZvcm1hdFJvd3M7XG5leHBvcnRzLnRzdlBhcnNlID0gdHN2UGFyc2U7XG5leHBvcnRzLnRzdlBhcnNlUm93cyA9IHRzdlBhcnNlUm93cztcbmV4cG9ydHMudHN2Rm9ybWF0ID0gdHN2Rm9ybWF0O1xuZXhwb3J0cy50c3ZGb3JtYXRSb3dzID0gdHN2Rm9ybWF0Um93cztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtZWFzZS8gVmVyc2lvbiAxLjAuMy4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBsaW5lYXIodCkge1xuICByZXR1cm4gK3Q7XG59XG5cbmZ1bmN0aW9uIHF1YWRJbih0KSB7XG4gIHJldHVybiB0ICogdDtcbn1cblxuZnVuY3Rpb24gcXVhZE91dCh0KSB7XG4gIHJldHVybiB0ICogKDIgLSB0KTtcbn1cblxuZnVuY3Rpb24gcXVhZEluT3V0KHQpIHtcbiAgcmV0dXJuICgodCAqPSAyKSA8PSAxID8gdCAqIHQgOiAtLXQgKiAoMiAtIHQpICsgMSkgLyAyO1xufVxuXG5mdW5jdGlvbiBjdWJpY0luKHQpIHtcbiAgcmV0dXJuIHQgKiB0ICogdDtcbn1cblxuZnVuY3Rpb24gY3ViaWNPdXQodCkge1xuICByZXR1cm4gLS10ICogdCAqIHQgKyAxO1xufVxuXG5mdW5jdGlvbiBjdWJpY0luT3V0KHQpIHtcbiAgcmV0dXJuICgodCAqPSAyKSA8PSAxID8gdCAqIHQgKiB0IDogKHQgLT0gMikgKiB0ICogdCArIDIpIC8gMjtcbn1cblxudmFyIGV4cG9uZW50ID0gMztcblxudmFyIHBvbHlJbiA9IChmdW5jdGlvbiBjdXN0b20oZSkge1xuICBlID0gK2U7XG5cbiAgZnVuY3Rpb24gcG9seUluKHQpIHtcbiAgICByZXR1cm4gTWF0aC5wb3codCwgZSk7XG4gIH1cblxuICBwb2x5SW4uZXhwb25lbnQgPSBjdXN0b207XG5cbiAgcmV0dXJuIHBvbHlJbjtcbn0pKGV4cG9uZW50KTtcblxudmFyIHBvbHlPdXQgPSAoZnVuY3Rpb24gY3VzdG9tKGUpIHtcbiAgZSA9ICtlO1xuXG4gIGZ1bmN0aW9uIHBvbHlPdXQodCkge1xuICAgIHJldHVybiAxIC0gTWF0aC5wb3coMSAtIHQsIGUpO1xuICB9XG5cbiAgcG9seU91dC5leHBvbmVudCA9IGN1c3RvbTtcblxuICByZXR1cm4gcG9seU91dDtcbn0pKGV4cG9uZW50KTtcblxudmFyIHBvbHlJbk91dCA9IChmdW5jdGlvbiBjdXN0b20oZSkge1xuICBlID0gK2U7XG5cbiAgZnVuY3Rpb24gcG9seUluT3V0KHQpIHtcbiAgICByZXR1cm4gKCh0ICo9IDIpIDw9IDEgPyBNYXRoLnBvdyh0LCBlKSA6IDIgLSBNYXRoLnBvdygyIC0gdCwgZSkpIC8gMjtcbiAgfVxuXG4gIHBvbHlJbk91dC5leHBvbmVudCA9IGN1c3RvbTtcblxuICByZXR1cm4gcG9seUluT3V0O1xufSkoZXhwb25lbnQpO1xuXG52YXIgcGkgPSBNYXRoLlBJO1xudmFyIGhhbGZQaSA9IHBpIC8gMjtcblxuZnVuY3Rpb24gc2luSW4odCkge1xuICByZXR1cm4gMSAtIE1hdGguY29zKHQgKiBoYWxmUGkpO1xufVxuXG5mdW5jdGlvbiBzaW5PdXQodCkge1xuICByZXR1cm4gTWF0aC5zaW4odCAqIGhhbGZQaSk7XG59XG5cbmZ1bmN0aW9uIHNpbkluT3V0KHQpIHtcbiAgcmV0dXJuICgxIC0gTWF0aC5jb3MocGkgKiB0KSkgLyAyO1xufVxuXG5mdW5jdGlvbiBleHBJbih0KSB7XG4gIHJldHVybiBNYXRoLnBvdygyLCAxMCAqIHQgLSAxMCk7XG59XG5cbmZ1bmN0aW9uIGV4cE91dCh0KSB7XG4gIHJldHVybiAxIC0gTWF0aC5wb3coMiwgLTEwICogdCk7XG59XG5cbmZ1bmN0aW9uIGV4cEluT3V0KHQpIHtcbiAgcmV0dXJuICgodCAqPSAyKSA8PSAxID8gTWF0aC5wb3coMiwgMTAgKiB0IC0gMTApIDogMiAtIE1hdGgucG93KDIsIDEwIC0gMTAgKiB0KSkgLyAyO1xufVxuXG5mdW5jdGlvbiBjaXJjbGVJbih0KSB7XG4gIHJldHVybiAxIC0gTWF0aC5zcXJ0KDEgLSB0ICogdCk7XG59XG5cbmZ1bmN0aW9uIGNpcmNsZU91dCh0KSB7XG4gIHJldHVybiBNYXRoLnNxcnQoMSAtIC0tdCAqIHQpO1xufVxuXG5mdW5jdGlvbiBjaXJjbGVJbk91dCh0KSB7XG4gIHJldHVybiAoKHQgKj0gMikgPD0gMSA/IDEgLSBNYXRoLnNxcnQoMSAtIHQgKiB0KSA6IE1hdGguc3FydCgxIC0gKHQgLT0gMikgKiB0KSArIDEpIC8gMjtcbn1cblxudmFyIGIxID0gNCAvIDExO1xudmFyIGIyID0gNiAvIDExO1xudmFyIGIzID0gOCAvIDExO1xudmFyIGI0ID0gMyAvIDQ7XG52YXIgYjUgPSA5IC8gMTE7XG52YXIgYjYgPSAxMCAvIDExO1xudmFyIGI3ID0gMTUgLyAxNjtcbnZhciBiOCA9IDIxIC8gMjI7XG52YXIgYjkgPSA2MyAvIDY0O1xudmFyIGIwID0gMSAvIGIxIC8gYjE7XG5cbmZ1bmN0aW9uIGJvdW5jZUluKHQpIHtcbiAgcmV0dXJuIDEgLSBib3VuY2VPdXQoMSAtIHQpO1xufVxuXG5mdW5jdGlvbiBib3VuY2VPdXQodCkge1xuICByZXR1cm4gKHQgPSArdCkgPCBiMSA/IGIwICogdCAqIHQgOiB0IDwgYjMgPyBiMCAqICh0IC09IGIyKSAqIHQgKyBiNCA6IHQgPCBiNiA/IGIwICogKHQgLT0gYjUpICogdCArIGI3IDogYjAgKiAodCAtPSBiOCkgKiB0ICsgYjk7XG59XG5cbmZ1bmN0aW9uIGJvdW5jZUluT3V0KHQpIHtcbiAgcmV0dXJuICgodCAqPSAyKSA8PSAxID8gMSAtIGJvdW5jZU91dCgxIC0gdCkgOiBib3VuY2VPdXQodCAtIDEpICsgMSkgLyAyO1xufVxuXG52YXIgb3ZlcnNob290ID0gMS43MDE1ODtcblxudmFyIGJhY2tJbiA9IChmdW5jdGlvbiBjdXN0b20ocykge1xuICBzID0gK3M7XG5cbiAgZnVuY3Rpb24gYmFja0luKHQpIHtcbiAgICByZXR1cm4gdCAqIHQgKiAoKHMgKyAxKSAqIHQgLSBzKTtcbiAgfVxuXG4gIGJhY2tJbi5vdmVyc2hvb3QgPSBjdXN0b207XG5cbiAgcmV0dXJuIGJhY2tJbjtcbn0pKG92ZXJzaG9vdCk7XG5cbnZhciBiYWNrT3V0ID0gKGZ1bmN0aW9uIGN1c3RvbShzKSB7XG4gIHMgPSArcztcblxuICBmdW5jdGlvbiBiYWNrT3V0KHQpIHtcbiAgICByZXR1cm4gLS10ICogdCAqICgocyArIDEpICogdCArIHMpICsgMTtcbiAgfVxuXG4gIGJhY2tPdXQub3ZlcnNob290ID0gY3VzdG9tO1xuXG4gIHJldHVybiBiYWNrT3V0O1xufSkob3ZlcnNob290KTtcblxudmFyIGJhY2tJbk91dCA9IChmdW5jdGlvbiBjdXN0b20ocykge1xuICBzID0gK3M7XG5cbiAgZnVuY3Rpb24gYmFja0luT3V0KHQpIHtcbiAgICByZXR1cm4gKCh0ICo9IDIpIDwgMSA/IHQgKiB0ICogKChzICsgMSkgKiB0IC0gcykgOiAodCAtPSAyKSAqIHQgKiAoKHMgKyAxKSAqIHQgKyBzKSArIDIpIC8gMjtcbiAgfVxuXG4gIGJhY2tJbk91dC5vdmVyc2hvb3QgPSBjdXN0b207XG5cbiAgcmV0dXJuIGJhY2tJbk91dDtcbn0pKG92ZXJzaG9vdCk7XG5cbnZhciB0YXUgPSAyICogTWF0aC5QSTtcbnZhciBhbXBsaXR1ZGUgPSAxO1xudmFyIHBlcmlvZCA9IDAuMztcblxudmFyIGVsYXN0aWNJbiA9IChmdW5jdGlvbiBjdXN0b20oYSwgcCkge1xuICB2YXIgcyA9IE1hdGguYXNpbigxIC8gKGEgPSBNYXRoLm1heCgxLCBhKSkpICogKHAgLz0gdGF1KTtcblxuICBmdW5jdGlvbiBlbGFzdGljSW4odCkge1xuICAgIHJldHVybiBhICogTWF0aC5wb3coMiwgMTAgKiAtLXQpICogTWF0aC5zaW4oKHMgLSB0KSAvIHApO1xuICB9XG5cbiAgZWxhc3RpY0luLmFtcGxpdHVkZSA9IGZ1bmN0aW9uKGEpIHsgcmV0dXJuIGN1c3RvbShhLCBwICogdGF1KTsgfTtcbiAgZWxhc3RpY0luLnBlcmlvZCA9IGZ1bmN0aW9uKHApIHsgcmV0dXJuIGN1c3RvbShhLCBwKTsgfTtcblxuICByZXR1cm4gZWxhc3RpY0luO1xufSkoYW1wbGl0dWRlLCBwZXJpb2QpO1xuXG52YXIgZWxhc3RpY091dCA9IChmdW5jdGlvbiBjdXN0b20oYSwgcCkge1xuICB2YXIgcyA9IE1hdGguYXNpbigxIC8gKGEgPSBNYXRoLm1heCgxLCBhKSkpICogKHAgLz0gdGF1KTtcblxuICBmdW5jdGlvbiBlbGFzdGljT3V0KHQpIHtcbiAgICByZXR1cm4gMSAtIGEgKiBNYXRoLnBvdygyLCAtMTAgKiAodCA9ICt0KSkgKiBNYXRoLnNpbigodCArIHMpIC8gcCk7XG4gIH1cblxuICBlbGFzdGljT3V0LmFtcGxpdHVkZSA9IGZ1bmN0aW9uKGEpIHsgcmV0dXJuIGN1c3RvbShhLCBwICogdGF1KTsgfTtcbiAgZWxhc3RpY091dC5wZXJpb2QgPSBmdW5jdGlvbihwKSB7IHJldHVybiBjdXN0b20oYSwgcCk7IH07XG5cbiAgcmV0dXJuIGVsYXN0aWNPdXQ7XG59KShhbXBsaXR1ZGUsIHBlcmlvZCk7XG5cbnZhciBlbGFzdGljSW5PdXQgPSAoZnVuY3Rpb24gY3VzdG9tKGEsIHApIHtcbiAgdmFyIHMgPSBNYXRoLmFzaW4oMSAvIChhID0gTWF0aC5tYXgoMSwgYSkpKSAqIChwIC89IHRhdSk7XG5cbiAgZnVuY3Rpb24gZWxhc3RpY0luT3V0KHQpIHtcbiAgICByZXR1cm4gKCh0ID0gdCAqIDIgLSAxKSA8IDBcbiAgICAgICAgPyBhICogTWF0aC5wb3coMiwgMTAgKiB0KSAqIE1hdGguc2luKChzIC0gdCkgLyBwKVxuICAgICAgICA6IDIgLSBhICogTWF0aC5wb3coMiwgLTEwICogdCkgKiBNYXRoLnNpbigocyArIHQpIC8gcCkpIC8gMjtcbiAgfVxuXG4gIGVsYXN0aWNJbk91dC5hbXBsaXR1ZGUgPSBmdW5jdGlvbihhKSB7IHJldHVybiBjdXN0b20oYSwgcCAqIHRhdSk7IH07XG4gIGVsYXN0aWNJbk91dC5wZXJpb2QgPSBmdW5jdGlvbihwKSB7IHJldHVybiBjdXN0b20oYSwgcCk7IH07XG5cbiAgcmV0dXJuIGVsYXN0aWNJbk91dDtcbn0pKGFtcGxpdHVkZSwgcGVyaW9kKTtcblxuZXhwb3J0cy5lYXNlTGluZWFyID0gbGluZWFyO1xuZXhwb3J0cy5lYXNlUXVhZCA9IHF1YWRJbk91dDtcbmV4cG9ydHMuZWFzZVF1YWRJbiA9IHF1YWRJbjtcbmV4cG9ydHMuZWFzZVF1YWRPdXQgPSBxdWFkT3V0O1xuZXhwb3J0cy5lYXNlUXVhZEluT3V0ID0gcXVhZEluT3V0O1xuZXhwb3J0cy5lYXNlQ3ViaWMgPSBjdWJpY0luT3V0O1xuZXhwb3J0cy5lYXNlQ3ViaWNJbiA9IGN1YmljSW47XG5leHBvcnRzLmVhc2VDdWJpY091dCA9IGN1YmljT3V0O1xuZXhwb3J0cy5lYXNlQ3ViaWNJbk91dCA9IGN1YmljSW5PdXQ7XG5leHBvcnRzLmVhc2VQb2x5ID0gcG9seUluT3V0O1xuZXhwb3J0cy5lYXNlUG9seUluID0gcG9seUluO1xuZXhwb3J0cy5lYXNlUG9seU91dCA9IHBvbHlPdXQ7XG5leHBvcnRzLmVhc2VQb2x5SW5PdXQgPSBwb2x5SW5PdXQ7XG5leHBvcnRzLmVhc2VTaW4gPSBzaW5Jbk91dDtcbmV4cG9ydHMuZWFzZVNpbkluID0gc2luSW47XG5leHBvcnRzLmVhc2VTaW5PdXQgPSBzaW5PdXQ7XG5leHBvcnRzLmVhc2VTaW5Jbk91dCA9IHNpbkluT3V0O1xuZXhwb3J0cy5lYXNlRXhwID0gZXhwSW5PdXQ7XG5leHBvcnRzLmVhc2VFeHBJbiA9IGV4cEluO1xuZXhwb3J0cy5lYXNlRXhwT3V0ID0gZXhwT3V0O1xuZXhwb3J0cy5lYXNlRXhwSW5PdXQgPSBleHBJbk91dDtcbmV4cG9ydHMuZWFzZUNpcmNsZSA9IGNpcmNsZUluT3V0O1xuZXhwb3J0cy5lYXNlQ2lyY2xlSW4gPSBjaXJjbGVJbjtcbmV4cG9ydHMuZWFzZUNpcmNsZU91dCA9IGNpcmNsZU91dDtcbmV4cG9ydHMuZWFzZUNpcmNsZUluT3V0ID0gY2lyY2xlSW5PdXQ7XG5leHBvcnRzLmVhc2VCb3VuY2UgPSBib3VuY2VPdXQ7XG5leHBvcnRzLmVhc2VCb3VuY2VJbiA9IGJvdW5jZUluO1xuZXhwb3J0cy5lYXNlQm91bmNlT3V0ID0gYm91bmNlT3V0O1xuZXhwb3J0cy5lYXNlQm91bmNlSW5PdXQgPSBib3VuY2VJbk91dDtcbmV4cG9ydHMuZWFzZUJhY2sgPSBiYWNrSW5PdXQ7XG5leHBvcnRzLmVhc2VCYWNrSW4gPSBiYWNrSW47XG5leHBvcnRzLmVhc2VCYWNrT3V0ID0gYmFja091dDtcbmV4cG9ydHMuZWFzZUJhY2tJbk91dCA9IGJhY2tJbk91dDtcbmV4cG9ydHMuZWFzZUVsYXN0aWMgPSBlbGFzdGljT3V0O1xuZXhwb3J0cy5lYXNlRWxhc3RpY0luID0gZWxhc3RpY0luO1xuZXhwb3J0cy5lYXNlRWxhc3RpY091dCA9IGVsYXN0aWNPdXQ7XG5leHBvcnRzLmVhc2VFbGFzdGljSW5PdXQgPSBlbGFzdGljSW5PdXQ7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWZvcmNlLyBWZXJzaW9uIDEuMS4wLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIHJlcXVpcmUoJ2QzLXF1YWR0cmVlJyksIHJlcXVpcmUoJ2QzLWNvbGxlY3Rpb24nKSwgcmVxdWlyZSgnZDMtZGlzcGF0Y2gnKSwgcmVxdWlyZSgnZDMtdGltZXInKSkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ2QzLXF1YWR0cmVlJywgJ2QzLWNvbGxlY3Rpb24nLCAnZDMtZGlzcGF0Y2gnLCAnZDMtdGltZXInXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMyxnbG9iYWwuZDMpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLGQzUXVhZHRyZWUsZDNDb2xsZWN0aW9uLGQzRGlzcGF0Y2gsZDNUaW1lcikgeyAndXNlIHN0cmljdCc7XG5cbnZhciBjZW50ZXIgPSBmdW5jdGlvbih4LCB5KSB7XG4gIHZhciBub2RlcztcblxuICBpZiAoeCA9PSBudWxsKSB4ID0gMDtcbiAgaWYgKHkgPT0gbnVsbCkgeSA9IDA7XG5cbiAgZnVuY3Rpb24gZm9yY2UoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIG4gPSBub2Rlcy5sZW5ndGgsXG4gICAgICAgIG5vZGUsXG4gICAgICAgIHN4ID0gMCxcbiAgICAgICAgc3kgPSAwO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgbm9kZSA9IG5vZGVzW2ldLCBzeCArPSBub2RlLngsIHN5ICs9IG5vZGUueTtcbiAgICB9XG5cbiAgICBmb3IgKHN4ID0gc3ggLyBuIC0geCwgc3kgPSBzeSAvIG4gLSB5LCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgbm9kZSA9IG5vZGVzW2ldLCBub2RlLnggLT0gc3gsIG5vZGUueSAtPSBzeTtcbiAgICB9XG4gIH1cblxuICBmb3JjZS5pbml0aWFsaXplID0gZnVuY3Rpb24oXykge1xuICAgIG5vZGVzID0gXztcbiAgfTtcblxuICBmb3JjZS54ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHggPSArXywgZm9yY2UpIDogeDtcbiAgfTtcblxuICBmb3JjZS55ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHkgPSArXywgZm9yY2UpIDogeTtcbiAgfTtcblxuICByZXR1cm4gZm9yY2U7XG59O1xuXG52YXIgY29uc3RhbnQgPSBmdW5jdGlvbih4KSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4geDtcbiAgfTtcbn07XG5cbnZhciBqaWdnbGUgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIChNYXRoLnJhbmRvbSgpIC0gMC41KSAqIDFlLTY7XG59O1xuXG5mdW5jdGlvbiB4KGQpIHtcbiAgcmV0dXJuIGQueCArIGQudng7XG59XG5cbmZ1bmN0aW9uIHkoZCkge1xuICByZXR1cm4gZC55ICsgZC52eTtcbn1cblxudmFyIGNvbGxpZGUgPSBmdW5jdGlvbihyYWRpdXMpIHtcbiAgdmFyIG5vZGVzLFxuICAgICAgcmFkaWksXG4gICAgICBzdHJlbmd0aCA9IDEsXG4gICAgICBpdGVyYXRpb25zID0gMTtcblxuICBpZiAodHlwZW9mIHJhZGl1cyAhPT0gXCJmdW5jdGlvblwiKSByYWRpdXMgPSBjb25zdGFudChyYWRpdXMgPT0gbnVsbCA/IDEgOiArcmFkaXVzKTtcblxuICBmdW5jdGlvbiBmb3JjZSgpIHtcbiAgICB2YXIgaSwgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgICAgdHJlZSxcbiAgICAgICAgbm9kZSxcbiAgICAgICAgeGksXG4gICAgICAgIHlpLFxuICAgICAgICByaSxcbiAgICAgICAgcmkyO1xuXG4gICAgZm9yICh2YXIgayA9IDA7IGsgPCBpdGVyYXRpb25zOyArK2spIHtcbiAgICAgIHRyZWUgPSBkM1F1YWR0cmVlLnF1YWR0cmVlKG5vZGVzLCB4LCB5KS52aXNpdEFmdGVyKHByZXBhcmUpO1xuICAgICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICBub2RlID0gbm9kZXNbaV07XG4gICAgICAgIHJpID0gcmFkaWlbbm9kZS5pbmRleF0sIHJpMiA9IHJpICogcmk7XG4gICAgICAgIHhpID0gbm9kZS54ICsgbm9kZS52eDtcbiAgICAgICAgeWkgPSBub2RlLnkgKyBub2RlLnZ5O1xuICAgICAgICB0cmVlLnZpc2l0KGFwcGx5KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhcHBseShxdWFkLCB4MCwgeTAsIHgxLCB5MSkge1xuICAgICAgdmFyIGRhdGEgPSBxdWFkLmRhdGEsIHJqID0gcXVhZC5yLCByID0gcmkgKyByajtcbiAgICAgIGlmIChkYXRhKSB7XG4gICAgICAgIGlmIChkYXRhLmluZGV4ID4gbm9kZS5pbmRleCkge1xuICAgICAgICAgIHZhciB4ID0geGkgLSBkYXRhLnggLSBkYXRhLnZ4LFxuICAgICAgICAgICAgICB5ID0geWkgLSBkYXRhLnkgLSBkYXRhLnZ5LFxuICAgICAgICAgICAgICBsID0geCAqIHggKyB5ICogeTtcbiAgICAgICAgICBpZiAobCA8IHIgKiByKSB7XG4gICAgICAgICAgICBpZiAoeCA9PT0gMCkgeCA9IGppZ2dsZSgpLCBsICs9IHggKiB4O1xuICAgICAgICAgICAgaWYgKHkgPT09IDApIHkgPSBqaWdnbGUoKSwgbCArPSB5ICogeTtcbiAgICAgICAgICAgIGwgPSAociAtIChsID0gTWF0aC5zcXJ0KGwpKSkgLyBsICogc3RyZW5ndGg7XG4gICAgICAgICAgICBub2RlLnZ4ICs9ICh4ICo9IGwpICogKHIgPSAocmogKj0gcmopIC8gKHJpMiArIHJqKSk7XG4gICAgICAgICAgICBub2RlLnZ5ICs9ICh5ICo9IGwpICogcjtcbiAgICAgICAgICAgIGRhdGEudnggLT0geCAqIChyID0gMSAtIHIpO1xuICAgICAgICAgICAgZGF0YS52eSAtPSB5ICogcjtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHgwID4geGkgKyByIHx8IHgxIDwgeGkgLSByIHx8IHkwID4geWkgKyByIHx8IHkxIDwgeWkgLSByO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHByZXBhcmUocXVhZCkge1xuICAgIGlmIChxdWFkLmRhdGEpIHJldHVybiBxdWFkLnIgPSByYWRpaVtxdWFkLmRhdGEuaW5kZXhdO1xuICAgIGZvciAodmFyIGkgPSBxdWFkLnIgPSAwOyBpIDwgNDsgKytpKSB7XG4gICAgICBpZiAocXVhZFtpXSAmJiBxdWFkW2ldLnIgPiBxdWFkLnIpIHtcbiAgICAgICAgcXVhZC5yID0gcXVhZFtpXS5yO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoLCBub2RlO1xuICAgIHJhZGlpID0gbmV3IEFycmF5KG4pO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIG5vZGUgPSBub2Rlc1tpXSwgcmFkaWlbbm9kZS5pbmRleF0gPSArcmFkaXVzKG5vZGUsIGksIG5vZGVzKTtcbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICAgIGluaXRpYWxpemUoKTtcbiAgfTtcblxuICBmb3JjZS5pdGVyYXRpb25zID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGl0ZXJhdGlvbnMgPSArXywgZm9yY2UpIDogaXRlcmF0aW9ucztcbiAgfTtcblxuICBmb3JjZS5zdHJlbmd0aCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzdHJlbmd0aCA9ICtfLCBmb3JjZSkgOiBzdHJlbmd0aDtcbiAgfTtcblxuICBmb3JjZS5yYWRpdXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogcmFkaXVzO1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbmZ1bmN0aW9uIGluZGV4KGQpIHtcbiAgcmV0dXJuIGQuaW5kZXg7XG59XG5cbmZ1bmN0aW9uIGZpbmQobm9kZUJ5SWQsIG5vZGVJZCkge1xuICB2YXIgbm9kZSA9IG5vZGVCeUlkLmdldChub2RlSWQpO1xuICBpZiAoIW5vZGUpIHRocm93IG5ldyBFcnJvcihcIm1pc3Npbmc6IFwiICsgbm9kZUlkKTtcbiAgcmV0dXJuIG5vZGU7XG59XG5cbnZhciBsaW5rID0gZnVuY3Rpb24obGlua3MpIHtcbiAgdmFyIGlkID0gaW5kZXgsXG4gICAgICBzdHJlbmd0aCA9IGRlZmF1bHRTdHJlbmd0aCxcbiAgICAgIHN0cmVuZ3RocyxcbiAgICAgIGRpc3RhbmNlID0gY29uc3RhbnQoMzApLFxuICAgICAgZGlzdGFuY2VzLFxuICAgICAgbm9kZXMsXG4gICAgICBjb3VudCxcbiAgICAgIGJpYXMsXG4gICAgICBpdGVyYXRpb25zID0gMTtcblxuICBpZiAobGlua3MgPT0gbnVsbCkgbGlua3MgPSBbXTtcblxuICBmdW5jdGlvbiBkZWZhdWx0U3RyZW5ndGgobGluaykge1xuICAgIHJldHVybiAxIC8gTWF0aC5taW4oY291bnRbbGluay5zb3VyY2UuaW5kZXhdLCBjb3VudFtsaW5rLnRhcmdldC5pbmRleF0pO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9yY2UoYWxwaGEpIHtcbiAgICBmb3IgKHZhciBrID0gMCwgbiA9IGxpbmtzLmxlbmd0aDsgayA8IGl0ZXJhdGlvbnM7ICsraykge1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxpbmssIHNvdXJjZSwgdGFyZ2V0LCB4LCB5LCBsLCBiOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGxpbmsgPSBsaW5rc1tpXSwgc291cmNlID0gbGluay5zb3VyY2UsIHRhcmdldCA9IGxpbmsudGFyZ2V0O1xuICAgICAgICB4ID0gdGFyZ2V0LnggKyB0YXJnZXQudnggLSBzb3VyY2UueCAtIHNvdXJjZS52eCB8fCBqaWdnbGUoKTtcbiAgICAgICAgeSA9IHRhcmdldC55ICsgdGFyZ2V0LnZ5IC0gc291cmNlLnkgLSBzb3VyY2UudnkgfHwgamlnZ2xlKCk7XG4gICAgICAgIGwgPSBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7XG4gICAgICAgIGwgPSAobCAtIGRpc3RhbmNlc1tpXSkgLyBsICogYWxwaGEgKiBzdHJlbmd0aHNbaV07XG4gICAgICAgIHggKj0gbCwgeSAqPSBsO1xuICAgICAgICB0YXJnZXQudnggLT0geCAqIChiID0gYmlhc1tpXSk7XG4gICAgICAgIHRhcmdldC52eSAtPSB5ICogYjtcbiAgICAgICAgc291cmNlLnZ4ICs9IHggKiAoYiA9IDEgLSBiKTtcbiAgICAgICAgc291cmNlLnZ5ICs9IHkgKiBiO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuXG4gICAgdmFyIGksXG4gICAgICAgIG4gPSBub2Rlcy5sZW5ndGgsXG4gICAgICAgIG0gPSBsaW5rcy5sZW5ndGgsXG4gICAgICAgIG5vZGVCeUlkID0gZDNDb2xsZWN0aW9uLm1hcChub2RlcywgaWQpLFxuICAgICAgICBsaW5rO1xuXG4gICAgZm9yIChpID0gMCwgY291bnQgPSBuZXcgQXJyYXkobik7IGkgPCBtOyArK2kpIHtcbiAgICAgIGxpbmsgPSBsaW5rc1tpXSwgbGluay5pbmRleCA9IGk7XG4gICAgICBpZiAodHlwZW9mIGxpbmsuc291cmNlICE9PSBcIm9iamVjdFwiKSBsaW5rLnNvdXJjZSA9IGZpbmQobm9kZUJ5SWQsIGxpbmsuc291cmNlKTtcbiAgICAgIGlmICh0eXBlb2YgbGluay50YXJnZXQgIT09IFwib2JqZWN0XCIpIGxpbmsudGFyZ2V0ID0gZmluZChub2RlQnlJZCwgbGluay50YXJnZXQpO1xuICAgICAgY291bnRbbGluay5zb3VyY2UuaW5kZXhdID0gKGNvdW50W2xpbmsuc291cmNlLmluZGV4XSB8fCAwKSArIDE7XG4gICAgICBjb3VudFtsaW5rLnRhcmdldC5pbmRleF0gPSAoY291bnRbbGluay50YXJnZXQuaW5kZXhdIHx8IDApICsgMTtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwLCBiaWFzID0gbmV3IEFycmF5KG0pOyBpIDwgbTsgKytpKSB7XG4gICAgICBsaW5rID0gbGlua3NbaV0sIGJpYXNbaV0gPSBjb3VudFtsaW5rLnNvdXJjZS5pbmRleF0gLyAoY291bnRbbGluay5zb3VyY2UuaW5kZXhdICsgY291bnRbbGluay50YXJnZXQuaW5kZXhdKTtcbiAgICB9XG5cbiAgICBzdHJlbmd0aHMgPSBuZXcgQXJyYXkobSksIGluaXRpYWxpemVTdHJlbmd0aCgpO1xuICAgIGRpc3RhbmNlcyA9IG5ldyBBcnJheShtKSwgaW5pdGlhbGl6ZURpc3RhbmNlKCk7XG4gIH1cblxuICBmdW5jdGlvbiBpbml0aWFsaXplU3RyZW5ndGgoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuXG4gICAgZm9yICh2YXIgaSA9IDAsIG4gPSBsaW5rcy5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIHN0cmVuZ3Roc1tpXSA9ICtzdHJlbmd0aChsaW5rc1tpXSwgaSwgbGlua3MpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemVEaXN0YW5jZSgpIHtcbiAgICBpZiAoIW5vZGVzKSByZXR1cm47XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IGxpbmtzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgZGlzdGFuY2VzW2ldID0gK2Rpc3RhbmNlKGxpbmtzW2ldLCBpLCBsaW5rcyk7XG4gICAgfVxuICB9XG5cbiAgZm9yY2UuaW5pdGlhbGl6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICBub2RlcyA9IF87XG4gICAgaW5pdGlhbGl6ZSgpO1xuICB9O1xuXG4gIGZvcmNlLmxpbmtzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGxpbmtzID0gXywgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiBsaW5rcztcbiAgfTtcblxuICBmb3JjZS5pZCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChpZCA9IF8sIGZvcmNlKSA6IGlkO1xuICB9O1xuXG4gIGZvcmNlLml0ZXJhdGlvbnMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaXRlcmF0aW9ucyA9ICtfLCBmb3JjZSkgOiBpdGVyYXRpb25zO1xuICB9O1xuXG4gIGZvcmNlLnN0cmVuZ3RoID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cmVuZ3RoID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemVTdHJlbmd0aCgpLCBmb3JjZSkgOiBzdHJlbmd0aDtcbiAgfTtcblxuICBmb3JjZS5kaXN0YW5jZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkaXN0YW5jZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplRGlzdGFuY2UoKSwgZm9yY2UpIDogZGlzdGFuY2U7XG4gIH07XG5cbiAgcmV0dXJuIGZvcmNlO1xufTtcblxuZnVuY3Rpb24geCQxKGQpIHtcbiAgcmV0dXJuIGQueDtcbn1cblxuZnVuY3Rpb24geSQxKGQpIHtcbiAgcmV0dXJuIGQueTtcbn1cblxudmFyIGluaXRpYWxSYWRpdXMgPSAxMDtcbnZhciBpbml0aWFsQW5nbGUgPSBNYXRoLlBJICogKDMgLSBNYXRoLnNxcnQoNSkpO1xuXG52YXIgc2ltdWxhdGlvbiA9IGZ1bmN0aW9uKG5vZGVzKSB7XG4gIHZhciBzaW11bGF0aW9uLFxuICAgICAgYWxwaGEgPSAxLFxuICAgICAgYWxwaGFNaW4gPSAwLjAwMSxcbiAgICAgIGFscGhhRGVjYXkgPSAxIC0gTWF0aC5wb3coYWxwaGFNaW4sIDEgLyAzMDApLFxuICAgICAgYWxwaGFUYXJnZXQgPSAwLFxuICAgICAgdmVsb2NpdHlEZWNheSA9IDAuNixcbiAgICAgIGZvcmNlcyA9IGQzQ29sbGVjdGlvbi5tYXAoKSxcbiAgICAgIHN0ZXBwZXIgPSBkM1RpbWVyLnRpbWVyKHN0ZXApLFxuICAgICAgZXZlbnQgPSBkM0Rpc3BhdGNoLmRpc3BhdGNoKFwidGlja1wiLCBcImVuZFwiKTtcblxuICBpZiAobm9kZXMgPT0gbnVsbCkgbm9kZXMgPSBbXTtcblxuICBmdW5jdGlvbiBzdGVwKCkge1xuICAgIHRpY2soKTtcbiAgICBldmVudC5jYWxsKFwidGlja1wiLCBzaW11bGF0aW9uKTtcbiAgICBpZiAoYWxwaGEgPCBhbHBoYU1pbikge1xuICAgICAgc3RlcHBlci5zdG9wKCk7XG4gICAgICBldmVudC5jYWxsKFwiZW5kXCIsIHNpbXVsYXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRpY2soKSB7XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGgsIG5vZGU7XG5cbiAgICBhbHBoYSArPSAoYWxwaGFUYXJnZXQgLSBhbHBoYSkgKiBhbHBoYURlY2F5O1xuXG4gICAgZm9yY2VzLmVhY2goZnVuY3Rpb24oZm9yY2UpIHtcbiAgICAgIGZvcmNlKGFscGhhKTtcbiAgICB9KTtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgIGlmIChub2RlLmZ4ID09IG51bGwpIG5vZGUueCArPSBub2RlLnZ4ICo9IHZlbG9jaXR5RGVjYXk7XG4gICAgICBlbHNlIG5vZGUueCA9IG5vZGUuZngsIG5vZGUudnggPSAwO1xuICAgICAgaWYgKG5vZGUuZnkgPT0gbnVsbCkgbm9kZS55ICs9IG5vZGUudnkgKj0gdmVsb2NpdHlEZWNheTtcbiAgICAgIGVsc2Ugbm9kZS55ID0gbm9kZS5meSwgbm9kZS52eSA9IDA7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZU5vZGVzKCkge1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbm9kZXMubGVuZ3RoLCBub2RlOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUuaW5kZXggPSBpO1xuICAgICAgaWYgKGlzTmFOKG5vZGUueCkgfHwgaXNOYU4obm9kZS55KSkge1xuICAgICAgICB2YXIgcmFkaXVzID0gaW5pdGlhbFJhZGl1cyAqIE1hdGguc3FydChpKSwgYW5nbGUgPSBpICogaW5pdGlhbEFuZ2xlO1xuICAgICAgICBub2RlLnggPSByYWRpdXMgKiBNYXRoLmNvcyhhbmdsZSk7XG4gICAgICAgIG5vZGUueSA9IHJhZGl1cyAqIE1hdGguc2luKGFuZ2xlKTtcbiAgICAgIH1cbiAgICAgIGlmIChpc05hTihub2RlLnZ4KSB8fCBpc05hTihub2RlLnZ5KSkge1xuICAgICAgICBub2RlLnZ4ID0gbm9kZS52eSA9IDA7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gaW5pdGlhbGl6ZUZvcmNlKGZvcmNlKSB7XG4gICAgaWYgKGZvcmNlLmluaXRpYWxpemUpIGZvcmNlLmluaXRpYWxpemUobm9kZXMpO1xuICAgIHJldHVybiBmb3JjZTtcbiAgfVxuXG4gIGluaXRpYWxpemVOb2RlcygpO1xuXG4gIHJldHVybiBzaW11bGF0aW9uID0ge1xuICAgIHRpY2s6IHRpY2ssXG5cbiAgICByZXN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBzdGVwcGVyLnJlc3RhcnQoc3RlcCksIHNpbXVsYXRpb247XG4gICAgfSxcblxuICAgIHN0b3A6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHN0ZXBwZXIuc3RvcCgpLCBzaW11bGF0aW9uO1xuICAgIH0sXG5cbiAgICBub2RlczogZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZXMgPSBfLCBpbml0aWFsaXplTm9kZXMoKSwgZm9yY2VzLmVhY2goaW5pdGlhbGl6ZUZvcmNlKSwgc2ltdWxhdGlvbikgOiBub2RlcztcbiAgICB9LFxuXG4gICAgYWxwaGE6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGFscGhhID0gK18sIHNpbXVsYXRpb24pIDogYWxwaGE7XG4gICAgfSxcblxuICAgIGFscGhhTWluOiBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhbHBoYU1pbiA9ICtfLCBzaW11bGF0aW9uKSA6IGFscGhhTWluO1xuICAgIH0sXG5cbiAgICBhbHBoYURlY2F5OiBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhbHBoYURlY2F5ID0gK18sIHNpbXVsYXRpb24pIDogK2FscGhhRGVjYXk7XG4gICAgfSxcblxuICAgIGFscGhhVGFyZ2V0OiBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChhbHBoYVRhcmdldCA9ICtfLCBzaW11bGF0aW9uKSA6IGFscGhhVGFyZ2V0O1xuICAgIH0sXG5cbiAgICB2ZWxvY2l0eURlY2F5OiBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2ZWxvY2l0eURlY2F5ID0gMSAtIF8sIHNpbXVsYXRpb24pIDogMSAtIHZlbG9jaXR5RGVjYXk7XG4gICAgfSxcblxuICAgIGZvcmNlOiBmdW5jdGlvbihuYW1lLCBfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyAoKF8gPT0gbnVsbCA/IGZvcmNlcy5yZW1vdmUobmFtZSkgOiBmb3JjZXMuc2V0KG5hbWUsIGluaXRpYWxpemVGb3JjZShfKSkpLCBzaW11bGF0aW9uKSA6IGZvcmNlcy5nZXQobmFtZSk7XG4gICAgfSxcblxuICAgIGZpbmQ6IGZ1bmN0aW9uKHgsIHksIHJhZGl1cykge1xuICAgICAgdmFyIGkgPSAwLFxuICAgICAgICAgIG4gPSBub2Rlcy5sZW5ndGgsXG4gICAgICAgICAgZHgsXG4gICAgICAgICAgZHksXG4gICAgICAgICAgZDIsXG4gICAgICAgICAgbm9kZSxcbiAgICAgICAgICBjbG9zZXN0O1xuXG4gICAgICBpZiAocmFkaXVzID09IG51bGwpIHJhZGl1cyA9IEluZmluaXR5O1xuICAgICAgZWxzZSByYWRpdXMgKj0gcmFkaXVzO1xuXG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgICAgZHggPSB4IC0gbm9kZS54O1xuICAgICAgICBkeSA9IHkgLSBub2RlLnk7XG4gICAgICAgIGQyID0gZHggKiBkeCArIGR5ICogZHk7XG4gICAgICAgIGlmIChkMiA8IHJhZGl1cykgY2xvc2VzdCA9IG5vZGUsIHJhZGl1cyA9IGQyO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gY2xvc2VzdDtcbiAgICB9LFxuXG4gICAgb246IGZ1bmN0aW9uKG5hbWUsIF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID4gMSA/IChldmVudC5vbihuYW1lLCBfKSwgc2ltdWxhdGlvbikgOiBldmVudC5vbihuYW1lKTtcbiAgICB9XG4gIH07XG59O1xuXG52YXIgbWFueUJvZHkgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG5vZGVzLFxuICAgICAgbm9kZSxcbiAgICAgIGFscGhhLFxuICAgICAgc3RyZW5ndGggPSBjb25zdGFudCgtMzApLFxuICAgICAgc3RyZW5ndGhzLFxuICAgICAgZGlzdGFuY2VNaW4yID0gMSxcbiAgICAgIGRpc3RhbmNlTWF4MiA9IEluZmluaXR5LFxuICAgICAgdGhldGEyID0gMC44MTtcblxuICBmdW5jdGlvbiBmb3JjZShfKSB7XG4gICAgdmFyIGksIG4gPSBub2Rlcy5sZW5ndGgsIHRyZWUgPSBkM1F1YWR0cmVlLnF1YWR0cmVlKG5vZGVzLCB4JDEsIHkkMSkudmlzaXRBZnRlcihhY2N1bXVsYXRlKTtcbiAgICBmb3IgKGFscGhhID0gXywgaSA9IDA7IGkgPCBuOyArK2kpIG5vZGUgPSBub2Rlc1tpXSwgdHJlZS52aXNpdChhcHBseSk7XG4gIH1cblxuICBmdW5jdGlvbiBpbml0aWFsaXplKCkge1xuICAgIGlmICghbm9kZXMpIHJldHVybjtcbiAgICB2YXIgaSwgbiA9IG5vZGVzLmxlbmd0aCwgbm9kZTtcbiAgICBzdHJlbmd0aHMgPSBuZXcgQXJyYXkobik7XG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkgbm9kZSA9IG5vZGVzW2ldLCBzdHJlbmd0aHNbbm9kZS5pbmRleF0gPSArc3RyZW5ndGgobm9kZSwgaSwgbm9kZXMpO1xuICB9XG5cbiAgZnVuY3Rpb24gYWNjdW11bGF0ZShxdWFkKSB7XG4gICAgdmFyIHN0cmVuZ3RoID0gMCwgcSwgYywgd2VpZ2h0ID0gMCwgeCwgeSwgaTtcblxuICAgIC8vIEZvciBpbnRlcm5hbCBub2RlcywgYWNjdW11bGF0ZSBmb3JjZXMgZnJvbSBjaGlsZCBxdWFkcmFudHMuXG4gICAgaWYgKHF1YWQubGVuZ3RoKSB7XG4gICAgICBmb3IgKHggPSB5ID0gaSA9IDA7IGkgPCA0OyArK2kpIHtcbiAgICAgICAgaWYgKChxID0gcXVhZFtpXSkgJiYgKGMgPSBNYXRoLmFicyhxLnZhbHVlKSkpIHtcbiAgICAgICAgICBzdHJlbmd0aCArPSBxLnZhbHVlLCB3ZWlnaHQgKz0gYywgeCArPSBjICogcS54LCB5ICs9IGMgKiBxLnk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHF1YWQueCA9IHggLyB3ZWlnaHQ7XG4gICAgICBxdWFkLnkgPSB5IC8gd2VpZ2h0O1xuICAgIH1cblxuICAgIC8vIEZvciBsZWFmIG5vZGVzLCBhY2N1bXVsYXRlIGZvcmNlcyBmcm9tIGNvaW5jaWRlbnQgcXVhZHJhbnRzLlxuICAgIGVsc2Uge1xuICAgICAgcSA9IHF1YWQ7XG4gICAgICBxLnggPSBxLmRhdGEueDtcbiAgICAgIHEueSA9IHEuZGF0YS55O1xuICAgICAgZG8gc3RyZW5ndGggKz0gc3RyZW5ndGhzW3EuZGF0YS5pbmRleF07XG4gICAgICB3aGlsZSAocSA9IHEubmV4dCk7XG4gICAgfVxuXG4gICAgcXVhZC52YWx1ZSA9IHN0cmVuZ3RoO1xuICB9XG5cbiAgZnVuY3Rpb24gYXBwbHkocXVhZCwgeDEsIF8sIHgyKSB7XG4gICAgaWYgKCFxdWFkLnZhbHVlKSByZXR1cm4gdHJ1ZTtcblxuICAgIHZhciB4ID0gcXVhZC54IC0gbm9kZS54LFxuICAgICAgICB5ID0gcXVhZC55IC0gbm9kZS55LFxuICAgICAgICB3ID0geDIgLSB4MSxcbiAgICAgICAgbCA9IHggKiB4ICsgeSAqIHk7XG5cbiAgICAvLyBBcHBseSB0aGUgQmFybmVzLUh1dCBhcHByb3hpbWF0aW9uIGlmIHBvc3NpYmxlLlxuICAgIC8vIExpbWl0IGZvcmNlcyBmb3IgdmVyeSBjbG9zZSBub2RlczsgcmFuZG9taXplIGRpcmVjdGlvbiBpZiBjb2luY2lkZW50LlxuICAgIGlmICh3ICogdyAvIHRoZXRhMiA8IGwpIHtcbiAgICAgIGlmIChsIDwgZGlzdGFuY2VNYXgyKSB7XG4gICAgICAgIGlmICh4ID09PSAwKSB4ID0gamlnZ2xlKCksIGwgKz0geCAqIHg7XG4gICAgICAgIGlmICh5ID09PSAwKSB5ID0gamlnZ2xlKCksIGwgKz0geSAqIHk7XG4gICAgICAgIGlmIChsIDwgZGlzdGFuY2VNaW4yKSBsID0gTWF0aC5zcXJ0KGRpc3RhbmNlTWluMiAqIGwpO1xuICAgICAgICBub2RlLnZ4ICs9IHggKiBxdWFkLnZhbHVlICogYWxwaGEgLyBsO1xuICAgICAgICBub2RlLnZ5ICs9IHkgKiBxdWFkLnZhbHVlICogYWxwaGEgLyBsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlLCBwcm9jZXNzIHBvaW50cyBkaXJlY3RseS5cbiAgICBlbHNlIGlmIChxdWFkLmxlbmd0aCB8fCBsID49IGRpc3RhbmNlTWF4MikgcmV0dXJuO1xuXG4gICAgLy8gTGltaXQgZm9yY2VzIGZvciB2ZXJ5IGNsb3NlIG5vZGVzOyByYW5kb21pemUgZGlyZWN0aW9uIGlmIGNvaW5jaWRlbnQuXG4gICAgaWYgKHF1YWQuZGF0YSAhPT0gbm9kZSB8fCBxdWFkLm5leHQpIHtcbiAgICAgIGlmICh4ID09PSAwKSB4ID0gamlnZ2xlKCksIGwgKz0geCAqIHg7XG4gICAgICBpZiAoeSA9PT0gMCkgeSA9IGppZ2dsZSgpLCBsICs9IHkgKiB5O1xuICAgICAgaWYgKGwgPCBkaXN0YW5jZU1pbjIpIGwgPSBNYXRoLnNxcnQoZGlzdGFuY2VNaW4yICogbCk7XG4gICAgfVxuXG4gICAgZG8gaWYgKHF1YWQuZGF0YSAhPT0gbm9kZSkge1xuICAgICAgdyA9IHN0cmVuZ3Roc1txdWFkLmRhdGEuaW5kZXhdICogYWxwaGEgLyBsO1xuICAgICAgbm9kZS52eCArPSB4ICogdztcbiAgICAgIG5vZGUudnkgKz0geSAqIHc7XG4gICAgfSB3aGlsZSAocXVhZCA9IHF1YWQubmV4dCk7XG4gIH1cblxuICBmb3JjZS5pbml0aWFsaXplID0gZnVuY3Rpb24oXykge1xuICAgIG5vZGVzID0gXztcbiAgICBpbml0aWFsaXplKCk7XG4gIH07XG5cbiAgZm9yY2Uuc3RyZW5ndGggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RyZW5ndGggPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiBzdHJlbmd0aDtcbiAgfTtcblxuICBmb3JjZS5kaXN0YW5jZU1pbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkaXN0YW5jZU1pbjIgPSBfICogXywgZm9yY2UpIDogTWF0aC5zcXJ0KGRpc3RhbmNlTWluMik7XG4gIH07XG5cbiAgZm9yY2UuZGlzdGFuY2VNYXggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZGlzdGFuY2VNYXgyID0gXyAqIF8sIGZvcmNlKSA6IE1hdGguc3FydChkaXN0YW5jZU1heDIpO1xuICB9O1xuXG4gIGZvcmNlLnRoZXRhID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRoZXRhMiA9IF8gKiBfLCBmb3JjZSkgOiBNYXRoLnNxcnQodGhldGEyKTtcbiAgfTtcblxuICByZXR1cm4gZm9yY2U7XG59O1xuXG52YXIgcmFkaWFsID0gZnVuY3Rpb24ocmFkaXVzLCB4LCB5KSB7XG4gIHZhciBub2RlcyxcbiAgICAgIHN0cmVuZ3RoID0gY29uc3RhbnQoMC4xKSxcbiAgICAgIHN0cmVuZ3RocyxcbiAgICAgIHJhZGl1c2VzO1xuXG4gIGlmICh0eXBlb2YgcmFkaXVzICE9PSBcImZ1bmN0aW9uXCIpIHJhZGl1cyA9IGNvbnN0YW50KCtyYWRpdXMpO1xuICBpZiAoeCA9PSBudWxsKSB4ID0gMDtcbiAgaWYgKHkgPT0gbnVsbCkgeSA9IDA7XG5cbiAgZnVuY3Rpb24gZm9yY2UoYWxwaGEpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IG5vZGVzLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgdmFyIG5vZGUgPSBub2Rlc1tpXSxcbiAgICAgICAgICBkeCA9IG5vZGUueCAtIHggfHwgMWUtNixcbiAgICAgICAgICBkeSA9IG5vZGUueSAtIHkgfHwgMWUtNixcbiAgICAgICAgICByID0gTWF0aC5zcXJ0KGR4ICogZHggKyBkeSAqIGR5KSxcbiAgICAgICAgICBrID0gKHJhZGl1c2VzW2ldIC0gcikgKiBzdHJlbmd0aHNbaV0gKiBhbHBoYSAvIHI7XG4gICAgICBub2RlLnZ4ICs9IGR4ICogaztcbiAgICAgIG5vZGUudnkgKz0gZHkgKiBrO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoO1xuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShuKTtcbiAgICByYWRpdXNlcyA9IG5ldyBBcnJheShuKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICByYWRpdXNlc1tpXSA9ICtyYWRpdXMobm9kZXNbaV0sIGksIG5vZGVzKTtcbiAgICAgIHN0cmVuZ3Roc1tpXSA9IGlzTmFOKHJhZGl1c2VzW2ldKSA/IDAgOiArc3RyZW5ndGgobm9kZXNbaV0sIGksIG5vZGVzKTtcbiAgICB9XG4gIH1cblxuICBmb3JjZS5pbml0aWFsaXplID0gZnVuY3Rpb24oXykge1xuICAgIG5vZGVzID0gXywgaW5pdGlhbGl6ZSgpO1xuICB9O1xuXG4gIGZvcmNlLnN0cmVuZ3RoID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0cmVuZ3RoID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGluaXRpYWxpemUoKSwgZm9yY2UpIDogc3RyZW5ndGg7XG4gIH07XG5cbiAgZm9yY2UucmFkaXVzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHJhZGl1cyA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHJhZGl1cztcbiAgfTtcblxuICBmb3JjZS54ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHggPSArXywgZm9yY2UpIDogeDtcbiAgfTtcblxuICBmb3JjZS55ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHkgPSArXywgZm9yY2UpIDogeTtcbiAgfTtcblxuICByZXR1cm4gZm9yY2U7XG59O1xuXG52YXIgeCQyID0gZnVuY3Rpb24oeCkge1xuICB2YXIgc3RyZW5ndGggPSBjb25zdGFudCgwLjEpLFxuICAgICAgbm9kZXMsXG4gICAgICBzdHJlbmd0aHMsXG4gICAgICB4ejtcblxuICBpZiAodHlwZW9mIHggIT09IFwiZnVuY3Rpb25cIikgeCA9IGNvbnN0YW50KHggPT0gbnVsbCA/IDAgOiAreCk7XG5cbiAgZnVuY3Rpb24gZm9yY2UoYWxwaGEpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgbiA9IG5vZGVzLmxlbmd0aCwgbm9kZTsgaSA8IG47ICsraSkge1xuICAgICAgbm9kZSA9IG5vZGVzW2ldLCBub2RlLnZ4ICs9ICh4eltpXSAtIG5vZGUueCkgKiBzdHJlbmd0aHNbaV0gKiBhbHBoYTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBpbml0aWFsaXplKCkge1xuICAgIGlmICghbm9kZXMpIHJldHVybjtcbiAgICB2YXIgaSwgbiA9IG5vZGVzLmxlbmd0aDtcbiAgICBzdHJlbmd0aHMgPSBuZXcgQXJyYXkobik7XG4gICAgeHogPSBuZXcgQXJyYXkobik7XG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgc3RyZW5ndGhzW2ldID0gaXNOYU4oeHpbaV0gPSAreChub2Rlc1tpXSwgaSwgbm9kZXMpKSA/IDAgOiArc3RyZW5ndGgobm9kZXNbaV0sIGksIG5vZGVzKTtcbiAgICB9XG4gIH1cblxuICBmb3JjZS5pbml0aWFsaXplID0gZnVuY3Rpb24oXykge1xuICAgIG5vZGVzID0gXztcbiAgICBpbml0aWFsaXplKCk7XG4gIH07XG5cbiAgZm9yY2Uuc3RyZW5ndGggPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc3RyZW5ndGggPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiBzdHJlbmd0aDtcbiAgfTtcblxuICBmb3JjZS54ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHggPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgaW5pdGlhbGl6ZSgpLCBmb3JjZSkgOiB4O1xuICB9O1xuXG4gIHJldHVybiBmb3JjZTtcbn07XG5cbnZhciB5JDIgPSBmdW5jdGlvbih5KSB7XG4gIHZhciBzdHJlbmd0aCA9IGNvbnN0YW50KDAuMSksXG4gICAgICBub2RlcyxcbiAgICAgIHN0cmVuZ3RocyxcbiAgICAgIHl6O1xuXG4gIGlmICh0eXBlb2YgeSAhPT0gXCJmdW5jdGlvblwiKSB5ID0gY29uc3RhbnQoeSA9PSBudWxsID8gMCA6ICt5KTtcblxuICBmdW5jdGlvbiBmb3JjZShhbHBoYSkge1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gbm9kZXMubGVuZ3RoLCBub2RlOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUudnkgKz0gKHl6W2ldIC0gbm9kZS55KSAqIHN0cmVuZ3Roc1tpXSAqIGFscGhhO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGluaXRpYWxpemUoKSB7XG4gICAgaWYgKCFub2RlcykgcmV0dXJuO1xuICAgIHZhciBpLCBuID0gbm9kZXMubGVuZ3RoO1xuICAgIHN0cmVuZ3RocyA9IG5ldyBBcnJheShuKTtcbiAgICB5eiA9IG5ldyBBcnJheShuKTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBzdHJlbmd0aHNbaV0gPSBpc05hTih5eltpXSA9ICt5KG5vZGVzW2ldLCBpLCBub2RlcykpID8gMCA6ICtzdHJlbmd0aChub2Rlc1tpXSwgaSwgbm9kZXMpO1xuICAgIH1cbiAgfVxuXG4gIGZvcmNlLmluaXRpYWxpemUgPSBmdW5jdGlvbihfKSB7XG4gICAgbm9kZXMgPSBfO1xuICAgIGluaXRpYWxpemUoKTtcbiAgfTtcblxuICBmb3JjZS5zdHJlbmd0aCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzdHJlbmd0aCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHN0cmVuZ3RoO1xuICB9O1xuXG4gIGZvcmNlLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBpbml0aWFsaXplKCksIGZvcmNlKSA6IHk7XG4gIH07XG5cbiAgcmV0dXJuIGZvcmNlO1xufTtcblxuZXhwb3J0cy5mb3JjZUNlbnRlciA9IGNlbnRlcjtcbmV4cG9ydHMuZm9yY2VDb2xsaWRlID0gY29sbGlkZTtcbmV4cG9ydHMuZm9yY2VMaW5rID0gbGluaztcbmV4cG9ydHMuZm9yY2VNYW55Qm9keSA9IG1hbnlCb2R5O1xuZXhwb3J0cy5mb3JjZVJhZGlhbCA9IHJhZGlhbDtcbmV4cG9ydHMuZm9yY2VTaW11bGF0aW9uID0gc2ltdWxhdGlvbjtcbmV4cG9ydHMuZm9yY2VYID0geCQyO1xuZXhwb3J0cy5mb3JjZVkgPSB5JDI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWZvcm1hdC8gVmVyc2lvbiAxLjIuMi4gQ29weXJpZ2h0IDIwMTggTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG4vLyBDb21wdXRlcyB0aGUgZGVjaW1hbCBjb2VmZmljaWVudCBhbmQgZXhwb25lbnQgb2YgdGhlIHNwZWNpZmllZCBudW1iZXIgeCB3aXRoXG4vLyBzaWduaWZpY2FudCBkaWdpdHMgcCwgd2hlcmUgeCBpcyBwb3NpdGl2ZSBhbmQgcCBpcyBpbiBbMSwgMjFdIG9yIHVuZGVmaW5lZC5cbi8vIEZvciBleGFtcGxlLCBmb3JtYXREZWNpbWFsKDEuMjMpIHJldHVybnMgW1wiMTIzXCIsIDBdLlxudmFyIGZvcm1hdERlY2ltYWwgPSBmdW5jdGlvbih4LCBwKSB7XG4gIGlmICgoaSA9ICh4ID0gcCA/IHgudG9FeHBvbmVudGlhbChwIC0gMSkgOiB4LnRvRXhwb25lbnRpYWwoKSkuaW5kZXhPZihcImVcIikpIDwgMCkgcmV0dXJuIG51bGw7IC8vIE5hTiwgwrFJbmZpbml0eVxuICB2YXIgaSwgY29lZmZpY2llbnQgPSB4LnNsaWNlKDAsIGkpO1xuXG4gIC8vIFRoZSBzdHJpbmcgcmV0dXJuZWQgYnkgdG9FeHBvbmVudGlhbCBlaXRoZXIgaGFzIHRoZSBmb3JtIFxcZFxcLlxcZCtlWy0rXVxcZCtcbiAgLy8gKGUuZy4sIDEuMmUrMykgb3IgdGhlIGZvcm0gXFxkZVstK11cXGQrIChlLmcuLCAxZSszKS5cbiAgcmV0dXJuIFtcbiAgICBjb2VmZmljaWVudC5sZW5ndGggPiAxID8gY29lZmZpY2llbnRbMF0gKyBjb2VmZmljaWVudC5zbGljZSgyKSA6IGNvZWZmaWNpZW50LFxuICAgICt4LnNsaWNlKGkgKyAxKVxuICBdO1xufTtcblxudmFyIGV4cG9uZW50ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4geCA9IGZvcm1hdERlY2ltYWwoTWF0aC5hYnMoeCkpLCB4ID8geFsxXSA6IE5hTjtcbn07XG5cbnZhciBmb3JtYXRHcm91cCA9IGZ1bmN0aW9uKGdyb3VwaW5nLCB0aG91c2FuZHMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCB3aWR0aCkge1xuICAgIHZhciBpID0gdmFsdWUubGVuZ3RoLFxuICAgICAgICB0ID0gW10sXG4gICAgICAgIGogPSAwLFxuICAgICAgICBnID0gZ3JvdXBpbmdbMF0sXG4gICAgICAgIGxlbmd0aCA9IDA7XG5cbiAgICB3aGlsZSAoaSA+IDAgJiYgZyA+IDApIHtcbiAgICAgIGlmIChsZW5ndGggKyBnICsgMSA+IHdpZHRoKSBnID0gTWF0aC5tYXgoMSwgd2lkdGggLSBsZW5ndGgpO1xuICAgICAgdC5wdXNoKHZhbHVlLnN1YnN0cmluZyhpIC09IGcsIGkgKyBnKSk7XG4gICAgICBpZiAoKGxlbmd0aCArPSBnICsgMSkgPiB3aWR0aCkgYnJlYWs7XG4gICAgICBnID0gZ3JvdXBpbmdbaiA9IChqICsgMSkgJSBncm91cGluZy5sZW5ndGhdO1xuICAgIH1cblxuICAgIHJldHVybiB0LnJldmVyc2UoKS5qb2luKHRob3VzYW5kcyk7XG4gIH07XG59O1xuXG52YXIgZm9ybWF0TnVtZXJhbHMgPSBmdW5jdGlvbihudW1lcmFscykge1xuICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmVwbGFjZSgvWzAtOV0vZywgZnVuY3Rpb24oaSkge1xuICAgICAgcmV0dXJuIG51bWVyYWxzWytpXTtcbiAgICB9KTtcbiAgfTtcbn07XG5cbnZhciBmb3JtYXREZWZhdWx0ID0gZnVuY3Rpb24oeCwgcCkge1xuICB4ID0geC50b1ByZWNpc2lvbihwKTtcblxuICBvdXQ6IGZvciAodmFyIG4gPSB4Lmxlbmd0aCwgaSA9IDEsIGkwID0gLTEsIGkxOyBpIDwgbjsgKytpKSB7XG4gICAgc3dpdGNoICh4W2ldKSB7XG4gICAgICBjYXNlIFwiLlwiOiBpMCA9IGkxID0gaTsgYnJlYWs7XG4gICAgICBjYXNlIFwiMFwiOiBpZiAoaTAgPT09IDApIGkwID0gaTsgaTEgPSBpOyBicmVhaztcbiAgICAgIGNhc2UgXCJlXCI6IGJyZWFrIG91dDtcbiAgICAgIGRlZmF1bHQ6IGlmIChpMCA+IDApIGkwID0gMDsgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGkwID4gMCA/IHguc2xpY2UoMCwgaTApICsgeC5zbGljZShpMSArIDEpIDogeDtcbn07XG5cbnZhciBwcmVmaXhFeHBvbmVudDtcblxudmFyIGZvcm1hdFByZWZpeEF1dG8gPSBmdW5jdGlvbih4LCBwKSB7XG4gIHZhciBkID0gZm9ybWF0RGVjaW1hbCh4LCBwKTtcbiAgaWYgKCFkKSByZXR1cm4geCArIFwiXCI7XG4gIHZhciBjb2VmZmljaWVudCA9IGRbMF0sXG4gICAgICBleHBvbmVudCA9IGRbMV0sXG4gICAgICBpID0gZXhwb25lbnQgLSAocHJlZml4RXhwb25lbnQgPSBNYXRoLm1heCgtOCwgTWF0aC5taW4oOCwgTWF0aC5mbG9vcihleHBvbmVudCAvIDMpKSkgKiAzKSArIDEsXG4gICAgICBuID0gY29lZmZpY2llbnQubGVuZ3RoO1xuICByZXR1cm4gaSA9PT0gbiA/IGNvZWZmaWNpZW50XG4gICAgICA6IGkgPiBuID8gY29lZmZpY2llbnQgKyBuZXcgQXJyYXkoaSAtIG4gKyAxKS5qb2luKFwiMFwiKVxuICAgICAgOiBpID4gMCA/IGNvZWZmaWNpZW50LnNsaWNlKDAsIGkpICsgXCIuXCIgKyBjb2VmZmljaWVudC5zbGljZShpKVxuICAgICAgOiBcIjAuXCIgKyBuZXcgQXJyYXkoMSAtIGkpLmpvaW4oXCIwXCIpICsgZm9ybWF0RGVjaW1hbCh4LCBNYXRoLm1heCgwLCBwICsgaSAtIDEpKVswXTsgLy8gbGVzcyB0aGFuIDF5IVxufTtcblxudmFyIGZvcm1hdFJvdW5kZWQgPSBmdW5jdGlvbih4LCBwKSB7XG4gIHZhciBkID0gZm9ybWF0RGVjaW1hbCh4LCBwKTtcbiAgaWYgKCFkKSByZXR1cm4geCArIFwiXCI7XG4gIHZhciBjb2VmZmljaWVudCA9IGRbMF0sXG4gICAgICBleHBvbmVudCA9IGRbMV07XG4gIHJldHVybiBleHBvbmVudCA8IDAgPyBcIjAuXCIgKyBuZXcgQXJyYXkoLWV4cG9uZW50KS5qb2luKFwiMFwiKSArIGNvZWZmaWNpZW50XG4gICAgICA6IGNvZWZmaWNpZW50Lmxlbmd0aCA+IGV4cG9uZW50ICsgMSA/IGNvZWZmaWNpZW50LnNsaWNlKDAsIGV4cG9uZW50ICsgMSkgKyBcIi5cIiArIGNvZWZmaWNpZW50LnNsaWNlKGV4cG9uZW50ICsgMSlcbiAgICAgIDogY29lZmZpY2llbnQgKyBuZXcgQXJyYXkoZXhwb25lbnQgLSBjb2VmZmljaWVudC5sZW5ndGggKyAyKS5qb2luKFwiMFwiKTtcbn07XG5cbnZhciBmb3JtYXRUeXBlcyA9IHtcbiAgXCJcIjogZm9ybWF0RGVmYXVsdCxcbiAgXCIlXCI6IGZ1bmN0aW9uKHgsIHApIHsgcmV0dXJuICh4ICogMTAwKS50b0ZpeGVkKHApOyB9LFxuICBcImJcIjogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5yb3VuZCh4KS50b1N0cmluZygyKTsgfSxcbiAgXCJjXCI6IGZ1bmN0aW9uKHgpIHsgcmV0dXJuIHggKyBcIlwiOyB9LFxuICBcImRcIjogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5yb3VuZCh4KS50b1N0cmluZygxMCk7IH0sXG4gIFwiZVwiOiBmdW5jdGlvbih4LCBwKSB7IHJldHVybiB4LnRvRXhwb25lbnRpYWwocCk7IH0sXG4gIFwiZlwiOiBmdW5jdGlvbih4LCBwKSB7IHJldHVybiB4LnRvRml4ZWQocCk7IH0sXG4gIFwiZ1wiOiBmdW5jdGlvbih4LCBwKSB7IHJldHVybiB4LnRvUHJlY2lzaW9uKHApOyB9LFxuICBcIm9cIjogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5yb3VuZCh4KS50b1N0cmluZyg4KTsgfSxcbiAgXCJwXCI6IGZ1bmN0aW9uKHgsIHApIHsgcmV0dXJuIGZvcm1hdFJvdW5kZWQoeCAqIDEwMCwgcCk7IH0sXG4gIFwiclwiOiBmb3JtYXRSb3VuZGVkLFxuICBcInNcIjogZm9ybWF0UHJlZml4QXV0byxcbiAgXCJYXCI6IGZ1bmN0aW9uKHgpIHsgcmV0dXJuIE1hdGgucm91bmQoeCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCk7IH0sXG4gIFwieFwiOiBmdW5jdGlvbih4KSB7IHJldHVybiBNYXRoLnJvdW5kKHgpLnRvU3RyaW5nKDE2KTsgfVxufTtcblxuLy8gW1tmaWxsXWFsaWduXVtzaWduXVtzeW1ib2xdWzBdW3dpZHRoXVssXVsucHJlY2lzaW9uXVt0eXBlXVxudmFyIHJlID0gL14oPzooLik/KFs8Pj1eXSkpPyhbK1xcLVxcKCBdKT8oWyQjXSk/KDApPyhcXGQrKT8oLCk/KFxcLlxcZCspPyhbYS16JV0pPyQvaTtcblxuZnVuY3Rpb24gZm9ybWF0U3BlY2lmaWVyKHNwZWNpZmllcikge1xuICByZXR1cm4gbmV3IEZvcm1hdFNwZWNpZmllcihzcGVjaWZpZXIpO1xufVxuXG5mb3JtYXRTcGVjaWZpZXIucHJvdG90eXBlID0gRm9ybWF0U3BlY2lmaWVyLnByb3RvdHlwZTsgLy8gaW5zdGFuY2VvZlxuXG5mdW5jdGlvbiBGb3JtYXRTcGVjaWZpZXIoc3BlY2lmaWVyKSB7XG4gIGlmICghKG1hdGNoID0gcmUuZXhlYyhzcGVjaWZpZXIpKSkgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBmb3JtYXQ6IFwiICsgc3BlY2lmaWVyKTtcblxuICB2YXIgbWF0Y2gsXG4gICAgICBmaWxsID0gbWF0Y2hbMV0gfHwgXCIgXCIsXG4gICAgICBhbGlnbiA9IG1hdGNoWzJdIHx8IFwiPlwiLFxuICAgICAgc2lnbiA9IG1hdGNoWzNdIHx8IFwiLVwiLFxuICAgICAgc3ltYm9sID0gbWF0Y2hbNF0gfHwgXCJcIixcbiAgICAgIHplcm8gPSAhIW1hdGNoWzVdLFxuICAgICAgd2lkdGggPSBtYXRjaFs2XSAmJiArbWF0Y2hbNl0sXG4gICAgICBjb21tYSA9ICEhbWF0Y2hbN10sXG4gICAgICBwcmVjaXNpb24gPSBtYXRjaFs4XSAmJiArbWF0Y2hbOF0uc2xpY2UoMSksXG4gICAgICB0eXBlID0gbWF0Y2hbOV0gfHwgXCJcIjtcblxuICAvLyBUaGUgXCJuXCIgdHlwZSBpcyBhbiBhbGlhcyBmb3IgXCIsZ1wiLlxuICBpZiAodHlwZSA9PT0gXCJuXCIpIGNvbW1hID0gdHJ1ZSwgdHlwZSA9IFwiZ1wiO1xuXG4gIC8vIE1hcCBpbnZhbGlkIHR5cGVzIHRvIHRoZSBkZWZhdWx0IGZvcm1hdC5cbiAgZWxzZSBpZiAoIWZvcm1hdFR5cGVzW3R5cGVdKSB0eXBlID0gXCJcIjtcblxuICAvLyBJZiB6ZXJvIGZpbGwgaXMgc3BlY2lmaWVkLCBwYWRkaW5nIGdvZXMgYWZ0ZXIgc2lnbiBhbmQgYmVmb3JlIGRpZ2l0cy5cbiAgaWYgKHplcm8gfHwgKGZpbGwgPT09IFwiMFwiICYmIGFsaWduID09PSBcIj1cIikpIHplcm8gPSB0cnVlLCBmaWxsID0gXCIwXCIsIGFsaWduID0gXCI9XCI7XG5cbiAgdGhpcy5maWxsID0gZmlsbDtcbiAgdGhpcy5hbGlnbiA9IGFsaWduO1xuICB0aGlzLnNpZ24gPSBzaWduO1xuICB0aGlzLnN5bWJvbCA9IHN5bWJvbDtcbiAgdGhpcy56ZXJvID0gemVybztcbiAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICB0aGlzLmNvbW1hID0gY29tbWE7XG4gIHRoaXMucHJlY2lzaW9uID0gcHJlY2lzaW9uO1xuICB0aGlzLnR5cGUgPSB0eXBlO1xufVxuXG5Gb3JtYXRTcGVjaWZpZXIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmZpbGxcbiAgICAgICsgdGhpcy5hbGlnblxuICAgICAgKyB0aGlzLnNpZ25cbiAgICAgICsgdGhpcy5zeW1ib2xcbiAgICAgICsgKHRoaXMuemVybyA/IFwiMFwiIDogXCJcIilcbiAgICAgICsgKHRoaXMud2lkdGggPT0gbnVsbCA/IFwiXCIgOiBNYXRoLm1heCgxLCB0aGlzLndpZHRoIHwgMCkpXG4gICAgICArICh0aGlzLmNvbW1hID8gXCIsXCIgOiBcIlwiKVxuICAgICAgKyAodGhpcy5wcmVjaXNpb24gPT0gbnVsbCA/IFwiXCIgOiBcIi5cIiArIE1hdGgubWF4KDAsIHRoaXMucHJlY2lzaW9uIHwgMCkpXG4gICAgICArIHRoaXMudHlwZTtcbn07XG5cbnZhciBpZGVudGl0eSA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHg7XG59O1xuXG52YXIgcHJlZml4ZXMgPSBbXCJ5XCIsXCJ6XCIsXCJhXCIsXCJmXCIsXCJwXCIsXCJuXCIsXCLCtVwiLFwibVwiLFwiXCIsXCJrXCIsXCJNXCIsXCJHXCIsXCJUXCIsXCJQXCIsXCJFXCIsXCJaXCIsXCJZXCJdO1xuXG52YXIgZm9ybWF0TG9jYWxlID0gZnVuY3Rpb24obG9jYWxlKSB7XG4gIHZhciBncm91cCA9IGxvY2FsZS5ncm91cGluZyAmJiBsb2NhbGUudGhvdXNhbmRzID8gZm9ybWF0R3JvdXAobG9jYWxlLmdyb3VwaW5nLCBsb2NhbGUudGhvdXNhbmRzKSA6IGlkZW50aXR5LFxuICAgICAgY3VycmVuY3kgPSBsb2NhbGUuY3VycmVuY3ksXG4gICAgICBkZWNpbWFsID0gbG9jYWxlLmRlY2ltYWwsXG4gICAgICBudW1lcmFscyA9IGxvY2FsZS5udW1lcmFscyA/IGZvcm1hdE51bWVyYWxzKGxvY2FsZS5udW1lcmFscykgOiBpZGVudGl0eSxcbiAgICAgIHBlcmNlbnQgPSBsb2NhbGUucGVyY2VudCB8fCBcIiVcIjtcblxuICBmdW5jdGlvbiBuZXdGb3JtYXQoc3BlY2lmaWVyKSB7XG4gICAgc3BlY2lmaWVyID0gZm9ybWF0U3BlY2lmaWVyKHNwZWNpZmllcik7XG5cbiAgICB2YXIgZmlsbCA9IHNwZWNpZmllci5maWxsLFxuICAgICAgICBhbGlnbiA9IHNwZWNpZmllci5hbGlnbixcbiAgICAgICAgc2lnbiA9IHNwZWNpZmllci5zaWduLFxuICAgICAgICBzeW1ib2wgPSBzcGVjaWZpZXIuc3ltYm9sLFxuICAgICAgICB6ZXJvID0gc3BlY2lmaWVyLnplcm8sXG4gICAgICAgIHdpZHRoID0gc3BlY2lmaWVyLndpZHRoLFxuICAgICAgICBjb21tYSA9IHNwZWNpZmllci5jb21tYSxcbiAgICAgICAgcHJlY2lzaW9uID0gc3BlY2lmaWVyLnByZWNpc2lvbixcbiAgICAgICAgdHlwZSA9IHNwZWNpZmllci50eXBlO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgcHJlZml4IGFuZCBzdWZmaXguXG4gICAgLy8gRm9yIFNJLXByZWZpeCwgdGhlIHN1ZmZpeCBpcyBsYXppbHkgY29tcHV0ZWQuXG4gICAgdmFyIHByZWZpeCA9IHN5bWJvbCA9PT0gXCIkXCIgPyBjdXJyZW5jeVswXSA6IHN5bWJvbCA9PT0gXCIjXCIgJiYgL1tib3hYXS8udGVzdCh0eXBlKSA/IFwiMFwiICsgdHlwZS50b0xvd2VyQ2FzZSgpIDogXCJcIixcbiAgICAgICAgc3VmZml4ID0gc3ltYm9sID09PSBcIiRcIiA/IGN1cnJlbmN5WzFdIDogL1slcF0vLnRlc3QodHlwZSkgPyBwZXJjZW50IDogXCJcIjtcblxuICAgIC8vIFdoYXQgZm9ybWF0IGZ1bmN0aW9uIHNob3VsZCB3ZSB1c2U/XG4gICAgLy8gSXMgdGhpcyBhbiBpbnRlZ2VyIHR5cGU/XG4gICAgLy8gQ2FuIHRoaXMgdHlwZSBnZW5lcmF0ZSBleHBvbmVudGlhbCBub3RhdGlvbj9cbiAgICB2YXIgZm9ybWF0VHlwZSA9IGZvcm1hdFR5cGVzW3R5cGVdLFxuICAgICAgICBtYXliZVN1ZmZpeCA9ICF0eXBlIHx8IC9bZGVmZ3BycyVdLy50ZXN0KHR5cGUpO1xuXG4gICAgLy8gU2V0IHRoZSBkZWZhdWx0IHByZWNpc2lvbiBpZiBub3Qgc3BlY2lmaWVkLFxuICAgIC8vIG9yIGNsYW1wIHRoZSBzcGVjaWZpZWQgcHJlY2lzaW9uIHRvIHRoZSBzdXBwb3J0ZWQgcmFuZ2UuXG4gICAgLy8gRm9yIHNpZ25pZmljYW50IHByZWNpc2lvbiwgaXQgbXVzdCBiZSBpbiBbMSwgMjFdLlxuICAgIC8vIEZvciBmaXhlZCBwcmVjaXNpb24sIGl0IG11c3QgYmUgaW4gWzAsIDIwXS5cbiAgICBwcmVjaXNpb24gPSBwcmVjaXNpb24gPT0gbnVsbCA/ICh0eXBlID8gNiA6IDEyKVxuICAgICAgICA6IC9bZ3Byc10vLnRlc3QodHlwZSkgPyBNYXRoLm1heCgxLCBNYXRoLm1pbigyMSwgcHJlY2lzaW9uKSlcbiAgICAgICAgOiBNYXRoLm1heCgwLCBNYXRoLm1pbigyMCwgcHJlY2lzaW9uKSk7XG5cbiAgICBmdW5jdGlvbiBmb3JtYXQodmFsdWUpIHtcbiAgICAgIHZhciB2YWx1ZVByZWZpeCA9IHByZWZpeCxcbiAgICAgICAgICB2YWx1ZVN1ZmZpeCA9IHN1ZmZpeCxcbiAgICAgICAgICBpLCBuLCBjO1xuXG4gICAgICBpZiAodHlwZSA9PT0gXCJjXCIpIHtcbiAgICAgICAgdmFsdWVTdWZmaXggPSBmb3JtYXRUeXBlKHZhbHVlKSArIHZhbHVlU3VmZml4O1xuICAgICAgICB2YWx1ZSA9IFwiXCI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YWx1ZSA9ICt2YWx1ZTtcblxuICAgICAgICAvLyBQZXJmb3JtIHRoZSBpbml0aWFsIGZvcm1hdHRpbmcuXG4gICAgICAgIHZhciB2YWx1ZU5lZ2F0aXZlID0gdmFsdWUgPCAwO1xuICAgICAgICB2YWx1ZSA9IGZvcm1hdFR5cGUoTWF0aC5hYnModmFsdWUpLCBwcmVjaXNpb24pO1xuXG4gICAgICAgIC8vIElmIGEgbmVnYXRpdmUgdmFsdWUgcm91bmRzIHRvIHplcm8gZHVyaW5nIGZvcm1hdHRpbmcsIHRyZWF0IGFzIHBvc2l0aXZlLlxuICAgICAgICBpZiAodmFsdWVOZWdhdGl2ZSAmJiArdmFsdWUgPT09IDApIHZhbHVlTmVnYXRpdmUgPSBmYWxzZTtcblxuICAgICAgICAvLyBDb21wdXRlIHRoZSBwcmVmaXggYW5kIHN1ZmZpeC5cbiAgICAgICAgdmFsdWVQcmVmaXggPSAodmFsdWVOZWdhdGl2ZSA/IChzaWduID09PSBcIihcIiA/IHNpZ24gOiBcIi1cIikgOiBzaWduID09PSBcIi1cIiB8fCBzaWduID09PSBcIihcIiA/IFwiXCIgOiBzaWduKSArIHZhbHVlUHJlZml4O1xuICAgICAgICB2YWx1ZVN1ZmZpeCA9ICh0eXBlID09PSBcInNcIiA/IHByZWZpeGVzWzggKyBwcmVmaXhFeHBvbmVudCAvIDNdIDogXCJcIikgKyB2YWx1ZVN1ZmZpeCArICh2YWx1ZU5lZ2F0aXZlICYmIHNpZ24gPT09IFwiKFwiID8gXCIpXCIgOiBcIlwiKTtcblxuICAgICAgICAvLyBCcmVhayB0aGUgZm9ybWF0dGVkIHZhbHVlIGludG8gdGhlIGludGVnZXIg4oCcdmFsdWXigJ0gcGFydCB0aGF0IGNhbiBiZVxuICAgICAgICAvLyBncm91cGVkLCBhbmQgZnJhY3Rpb25hbCBvciBleHBvbmVudGlhbCDigJxzdWZmaXjigJ0gcGFydCB0aGF0IGlzIG5vdC5cbiAgICAgICAgaWYgKG1heWJlU3VmZml4KSB7XG4gICAgICAgICAgaSA9IC0xLCBuID0gdmFsdWUubGVuZ3RoO1xuICAgICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgICBpZiAoYyA9IHZhbHVlLmNoYXJDb2RlQXQoaSksIDQ4ID4gYyB8fCBjID4gNTcpIHtcbiAgICAgICAgICAgICAgdmFsdWVTdWZmaXggPSAoYyA9PT0gNDYgPyBkZWNpbWFsICsgdmFsdWUuc2xpY2UoaSArIDEpIDogdmFsdWUuc2xpY2UoaSkpICsgdmFsdWVTdWZmaXg7XG4gICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoMCwgaSk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBJZiB0aGUgZmlsbCBjaGFyYWN0ZXIgaXMgbm90IFwiMFwiLCBncm91cGluZyBpcyBhcHBsaWVkIGJlZm9yZSBwYWRkaW5nLlxuICAgICAgaWYgKGNvbW1hICYmICF6ZXJvKSB2YWx1ZSA9IGdyb3VwKHZhbHVlLCBJbmZpbml0eSk7XG5cbiAgICAgIC8vIENvbXB1dGUgdGhlIHBhZGRpbmcuXG4gICAgICB2YXIgbGVuZ3RoID0gdmFsdWVQcmVmaXgubGVuZ3RoICsgdmFsdWUubGVuZ3RoICsgdmFsdWVTdWZmaXgubGVuZ3RoLFxuICAgICAgICAgIHBhZGRpbmcgPSBsZW5ndGggPCB3aWR0aCA/IG5ldyBBcnJheSh3aWR0aCAtIGxlbmd0aCArIDEpLmpvaW4oZmlsbCkgOiBcIlwiO1xuXG4gICAgICAvLyBJZiB0aGUgZmlsbCBjaGFyYWN0ZXIgaXMgXCIwXCIsIGdyb3VwaW5nIGlzIGFwcGxpZWQgYWZ0ZXIgcGFkZGluZy5cbiAgICAgIGlmIChjb21tYSAmJiB6ZXJvKSB2YWx1ZSA9IGdyb3VwKHBhZGRpbmcgKyB2YWx1ZSwgcGFkZGluZy5sZW5ndGggPyB3aWR0aCAtIHZhbHVlU3VmZml4Lmxlbmd0aCA6IEluZmluaXR5KSwgcGFkZGluZyA9IFwiXCI7XG5cbiAgICAgIC8vIFJlY29uc3RydWN0IHRoZSBmaW5hbCBvdXRwdXQgYmFzZWQgb24gdGhlIGRlc2lyZWQgYWxpZ25tZW50LlxuICAgICAgc3dpdGNoIChhbGlnbikge1xuICAgICAgICBjYXNlIFwiPFwiOiB2YWx1ZSA9IHZhbHVlUHJlZml4ICsgdmFsdWUgKyB2YWx1ZVN1ZmZpeCArIHBhZGRpbmc7IGJyZWFrO1xuICAgICAgICBjYXNlIFwiPVwiOiB2YWx1ZSA9IHZhbHVlUHJlZml4ICsgcGFkZGluZyArIHZhbHVlICsgdmFsdWVTdWZmaXg7IGJyZWFrO1xuICAgICAgICBjYXNlIFwiXlwiOiB2YWx1ZSA9IHBhZGRpbmcuc2xpY2UoMCwgbGVuZ3RoID0gcGFkZGluZy5sZW5ndGggPj4gMSkgKyB2YWx1ZVByZWZpeCArIHZhbHVlICsgdmFsdWVTdWZmaXggKyBwYWRkaW5nLnNsaWNlKGxlbmd0aCk7IGJyZWFrO1xuICAgICAgICBkZWZhdWx0OiB2YWx1ZSA9IHBhZGRpbmcgKyB2YWx1ZVByZWZpeCArIHZhbHVlICsgdmFsdWVTdWZmaXg7IGJyZWFrO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gbnVtZXJhbHModmFsdWUpO1xuICAgIH1cblxuICAgIGZvcm1hdC50b1N0cmluZyA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHNwZWNpZmllciArIFwiXCI7XG4gICAgfTtcblxuICAgIHJldHVybiBmb3JtYXQ7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRQcmVmaXgoc3BlY2lmaWVyLCB2YWx1ZSkge1xuICAgIHZhciBmID0gbmV3Rm9ybWF0KChzcGVjaWZpZXIgPSBmb3JtYXRTcGVjaWZpZXIoc3BlY2lmaWVyKSwgc3BlY2lmaWVyLnR5cGUgPSBcImZcIiwgc3BlY2lmaWVyKSksXG4gICAgICAgIGUgPSBNYXRoLm1heCgtOCwgTWF0aC5taW4oOCwgTWF0aC5mbG9vcihleHBvbmVudCh2YWx1ZSkgLyAzKSkpICogMyxcbiAgICAgICAgayA9IE1hdGgucG93KDEwLCAtZSksXG4gICAgICAgIHByZWZpeCA9IHByZWZpeGVzWzggKyBlIC8gM107XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gZihrICogdmFsdWUpICsgcHJlZml4O1xuICAgIH07XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGZvcm1hdDogbmV3Rm9ybWF0LFxuICAgIGZvcm1hdFByZWZpeDogZm9ybWF0UHJlZml4XG4gIH07XG59O1xuXG52YXIgbG9jYWxlO1xuXG5cblxuZGVmYXVsdExvY2FsZSh7XG4gIGRlY2ltYWw6IFwiLlwiLFxuICB0aG91c2FuZHM6IFwiLFwiLFxuICBncm91cGluZzogWzNdLFxuICBjdXJyZW5jeTogW1wiJFwiLCBcIlwiXVxufSk7XG5cbmZ1bmN0aW9uIGRlZmF1bHRMb2NhbGUoZGVmaW5pdGlvbikge1xuICBsb2NhbGUgPSBmb3JtYXRMb2NhbGUoZGVmaW5pdGlvbik7XG4gIGV4cG9ydHMuZm9ybWF0ID0gbG9jYWxlLmZvcm1hdDtcbiAgZXhwb3J0cy5mb3JtYXRQcmVmaXggPSBsb2NhbGUuZm9ybWF0UHJlZml4O1xuICByZXR1cm4gbG9jYWxlO1xufVxuXG52YXIgcHJlY2lzaW9uRml4ZWQgPSBmdW5jdGlvbihzdGVwKSB7XG4gIHJldHVybiBNYXRoLm1heCgwLCAtZXhwb25lbnQoTWF0aC5hYnMoc3RlcCkpKTtcbn07XG5cbnZhciBwcmVjaXNpb25QcmVmaXggPSBmdW5jdGlvbihzdGVwLCB2YWx1ZSkge1xuICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5tYXgoLTgsIE1hdGgubWluKDgsIE1hdGguZmxvb3IoZXhwb25lbnQodmFsdWUpIC8gMykpKSAqIDMgLSBleHBvbmVudChNYXRoLmFicyhzdGVwKSkpO1xufTtcblxudmFyIHByZWNpc2lvblJvdW5kID0gZnVuY3Rpb24oc3RlcCwgbWF4KSB7XG4gIHN0ZXAgPSBNYXRoLmFicyhzdGVwKSwgbWF4ID0gTWF0aC5hYnMobWF4KSAtIHN0ZXA7XG4gIHJldHVybiBNYXRoLm1heCgwLCBleHBvbmVudChtYXgpIC0gZXhwb25lbnQoc3RlcCkpICsgMTtcbn07XG5cbmV4cG9ydHMuZm9ybWF0RGVmYXVsdExvY2FsZSA9IGRlZmF1bHRMb2NhbGU7XG5leHBvcnRzLmZvcm1hdExvY2FsZSA9IGZvcm1hdExvY2FsZTtcbmV4cG9ydHMuZm9ybWF0U3BlY2lmaWVyID0gZm9ybWF0U3BlY2lmaWVyO1xuZXhwb3J0cy5wcmVjaXNpb25GaXhlZCA9IHByZWNpc2lvbkZpeGVkO1xuZXhwb3J0cy5wcmVjaXNpb25QcmVmaXggPSBwcmVjaXNpb25QcmVmaXg7XG5leHBvcnRzLnByZWNpc2lvblJvdW5kID0gcHJlY2lzaW9uUm91bmQ7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLWdlby8gVmVyc2lvbiAxLjkuMS4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzLCByZXF1aXJlKCdkMy1hcnJheScpKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtYXJyYXknXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLGQzQXJyYXkpIHsgJ3VzZSBzdHJpY3QnO1xuXG4vLyBBZGRzIGZsb2F0aW5nIHBvaW50IG51bWJlcnMgd2l0aCB0d2ljZSB0aGUgbm9ybWFsIHByZWNpc2lvbi5cbi8vIFJlZmVyZW5jZTogSi4gUi4gU2hld2NodWssIEFkYXB0aXZlIFByZWNpc2lvbiBGbG9hdGluZy1Qb2ludCBBcml0aG1ldGljIGFuZFxuLy8gRmFzdCBSb2J1c3QgR2VvbWV0cmljIFByZWRpY2F0ZXMsIERpc2NyZXRlICYgQ29tcHV0YXRpb25hbCBHZW9tZXRyeSAxOCgzKVxuLy8gMzA14oCTMzYzICgxOTk3KS5cbi8vIENvZGUgYWRhcHRlZCBmcm9tIEdlb2dyYXBoaWNMaWIgYnkgQ2hhcmxlcyBGLiBGLiBLYXJuZXksXG4vLyBodHRwOi8vZ2VvZ3JhcGhpY2xpYi5zb3VyY2Vmb3JnZS5uZXQvXG5cbnZhciBhZGRlciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gbmV3IEFkZGVyO1xufTtcblxuZnVuY3Rpb24gQWRkZXIoKSB7XG4gIHRoaXMucmVzZXQoKTtcbn1cblxuQWRkZXIucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogQWRkZXIsXG4gIHJlc2V0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnMgPSAvLyByb3VuZGVkIHZhbHVlXG4gICAgdGhpcy50ID0gMDsgLy8gZXhhY3QgZXJyb3JcbiAgfSxcbiAgYWRkOiBmdW5jdGlvbih5KSB7XG4gICAgYWRkKHRlbXAsIHksIHRoaXMudCk7XG4gICAgYWRkKHRoaXMsIHRlbXAucywgdGhpcy5zKTtcbiAgICBpZiAodGhpcy5zKSB0aGlzLnQgKz0gdGVtcC50O1xuICAgIGVsc2UgdGhpcy5zID0gdGVtcC50O1xuICB9LFxuICB2YWx1ZU9mOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5zO1xuICB9XG59O1xuXG52YXIgdGVtcCA9IG5ldyBBZGRlcjtcblxuZnVuY3Rpb24gYWRkKGFkZGVyLCBhLCBiKSB7XG4gIHZhciB4ID0gYWRkZXIucyA9IGEgKyBiLFxuICAgICAgYnYgPSB4IC0gYSxcbiAgICAgIGF2ID0geCAtIGJ2O1xuICBhZGRlci50ID0gKGEgLSBhdikgKyAoYiAtIGJ2KTtcbn1cblxudmFyIGVwc2lsb24gPSAxZS02O1xudmFyIGVwc2lsb24yID0gMWUtMTI7XG52YXIgcGkgPSBNYXRoLlBJO1xudmFyIGhhbGZQaSA9IHBpIC8gMjtcbnZhciBxdWFydGVyUGkgPSBwaSAvIDQ7XG52YXIgdGF1ID0gcGkgKiAyO1xuXG52YXIgZGVncmVlcyA9IDE4MCAvIHBpO1xudmFyIHJhZGlhbnMgPSBwaSAvIDE4MDtcblxudmFyIGFicyA9IE1hdGguYWJzO1xudmFyIGF0YW4gPSBNYXRoLmF0YW47XG52YXIgYXRhbjIgPSBNYXRoLmF0YW4yO1xudmFyIGNvcyA9IE1hdGguY29zO1xudmFyIGNlaWwgPSBNYXRoLmNlaWw7XG52YXIgZXhwID0gTWF0aC5leHA7XG5cbnZhciBsb2cgPSBNYXRoLmxvZztcbnZhciBwb3cgPSBNYXRoLnBvdztcbnZhciBzaW4gPSBNYXRoLnNpbjtcbnZhciBzaWduID0gTWF0aC5zaWduIHx8IGZ1bmN0aW9uKHgpIHsgcmV0dXJuIHggPiAwID8gMSA6IHggPCAwID8gLTEgOiAwOyB9O1xudmFyIHNxcnQgPSBNYXRoLnNxcnQ7XG52YXIgdGFuID0gTWF0aC50YW47XG5cbmZ1bmN0aW9uIGFjb3MoeCkge1xuICByZXR1cm4geCA+IDEgPyAwIDogeCA8IC0xID8gcGkgOiBNYXRoLmFjb3MoeCk7XG59XG5cbmZ1bmN0aW9uIGFzaW4oeCkge1xuICByZXR1cm4geCA+IDEgPyBoYWxmUGkgOiB4IDwgLTEgPyAtaGFsZlBpIDogTWF0aC5hc2luKHgpO1xufVxuXG5mdW5jdGlvbiBoYXZlcnNpbih4KSB7XG4gIHJldHVybiAoeCA9IHNpbih4IC8gMikpICogeDtcbn1cblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbmZ1bmN0aW9uIHN0cmVhbUdlb21ldHJ5KGdlb21ldHJ5LCBzdHJlYW0pIHtcbiAgaWYgKGdlb21ldHJ5ICYmIHN0cmVhbUdlb21ldHJ5VHlwZS5oYXNPd25Qcm9wZXJ0eShnZW9tZXRyeS50eXBlKSkge1xuICAgIHN0cmVhbUdlb21ldHJ5VHlwZVtnZW9tZXRyeS50eXBlXShnZW9tZXRyeSwgc3RyZWFtKTtcbiAgfVxufVxuXG52YXIgc3RyZWFtT2JqZWN0VHlwZSA9IHtcbiAgRmVhdHVyZTogZnVuY3Rpb24ob2JqZWN0LCBzdHJlYW0pIHtcbiAgICBzdHJlYW1HZW9tZXRyeShvYmplY3QuZ2VvbWV0cnksIHN0cmVhbSk7XG4gIH0sXG4gIEZlYXR1cmVDb2xsZWN0aW9uOiBmdW5jdGlvbihvYmplY3QsIHN0cmVhbSkge1xuICAgIHZhciBmZWF0dXJlcyA9IG9iamVjdC5mZWF0dXJlcywgaSA9IC0xLCBuID0gZmVhdHVyZXMubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBuKSBzdHJlYW1HZW9tZXRyeShmZWF0dXJlc1tpXS5nZW9tZXRyeSwgc3RyZWFtKTtcbiAgfVxufTtcblxudmFyIHN0cmVhbUdlb21ldHJ5VHlwZSA9IHtcbiAgU3BoZXJlOiBmdW5jdGlvbihvYmplY3QsIHN0cmVhbSkge1xuICAgIHN0cmVhbS5zcGhlcmUoKTtcbiAgfSxcbiAgUG9pbnQ6IGZ1bmN0aW9uKG9iamVjdCwgc3RyZWFtKSB7XG4gICAgb2JqZWN0ID0gb2JqZWN0LmNvb3JkaW5hdGVzO1xuICAgIHN0cmVhbS5wb2ludChvYmplY3RbMF0sIG9iamVjdFsxXSwgb2JqZWN0WzJdKTtcbiAgfSxcbiAgTXVsdGlQb2ludDogZnVuY3Rpb24ob2JqZWN0LCBzdHJlYW0pIHtcbiAgICB2YXIgY29vcmRpbmF0ZXMgPSBvYmplY3QuY29vcmRpbmF0ZXMsIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgb2JqZWN0ID0gY29vcmRpbmF0ZXNbaV0sIHN0cmVhbS5wb2ludChvYmplY3RbMF0sIG9iamVjdFsxXSwgb2JqZWN0WzJdKTtcbiAgfSxcbiAgTGluZVN0cmluZzogZnVuY3Rpb24ob2JqZWN0LCBzdHJlYW0pIHtcbiAgICBzdHJlYW1MaW5lKG9iamVjdC5jb29yZGluYXRlcywgc3RyZWFtLCAwKTtcbiAgfSxcbiAgTXVsdGlMaW5lU3RyaW5nOiBmdW5jdGlvbihvYmplY3QsIHN0cmVhbSkge1xuICAgIHZhciBjb29yZGluYXRlcyA9IG9iamVjdC5jb29yZGluYXRlcywgaSA9IC0xLCBuID0gY29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBuKSBzdHJlYW1MaW5lKGNvb3JkaW5hdGVzW2ldLCBzdHJlYW0sIDApO1xuICB9LFxuICBQb2x5Z29uOiBmdW5jdGlvbihvYmplY3QsIHN0cmVhbSkge1xuICAgIHN0cmVhbVBvbHlnb24ob2JqZWN0LmNvb3JkaW5hdGVzLCBzdHJlYW0pO1xuICB9LFxuICBNdWx0aVBvbHlnb246IGZ1bmN0aW9uKG9iamVjdCwgc3RyZWFtKSB7XG4gICAgdmFyIGNvb3JkaW5hdGVzID0gb2JqZWN0LmNvb3JkaW5hdGVzLCBpID0gLTEsIG4gPSBjb29yZGluYXRlcy5sZW5ndGg7XG4gICAgd2hpbGUgKCsraSA8IG4pIHN0cmVhbVBvbHlnb24oY29vcmRpbmF0ZXNbaV0sIHN0cmVhbSk7XG4gIH0sXG4gIEdlb21ldHJ5Q29sbGVjdGlvbjogZnVuY3Rpb24ob2JqZWN0LCBzdHJlYW0pIHtcbiAgICB2YXIgZ2VvbWV0cmllcyA9IG9iamVjdC5nZW9tZXRyaWVzLCBpID0gLTEsIG4gPSBnZW9tZXRyaWVzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgc3RyZWFtR2VvbWV0cnkoZ2VvbWV0cmllc1tpXSwgc3RyZWFtKTtcbiAgfVxufTtcblxuZnVuY3Rpb24gc3RyZWFtTGluZShjb29yZGluYXRlcywgc3RyZWFtLCBjbG9zZWQpIHtcbiAgdmFyIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aCAtIGNsb3NlZCwgY29vcmRpbmF0ZTtcbiAgc3RyZWFtLmxpbmVTdGFydCgpO1xuICB3aGlsZSAoKytpIDwgbikgY29vcmRpbmF0ZSA9IGNvb3JkaW5hdGVzW2ldLCBzdHJlYW0ucG9pbnQoY29vcmRpbmF0ZVswXSwgY29vcmRpbmF0ZVsxXSwgY29vcmRpbmF0ZVsyXSk7XG4gIHN0cmVhbS5saW5lRW5kKCk7XG59XG5cbmZ1bmN0aW9uIHN0cmVhbVBvbHlnb24oY29vcmRpbmF0ZXMsIHN0cmVhbSkge1xuICB2YXIgaSA9IC0xLCBuID0gY29vcmRpbmF0ZXMubGVuZ3RoO1xuICBzdHJlYW0ucG9seWdvblN0YXJ0KCk7XG4gIHdoaWxlICgrK2kgPCBuKSBzdHJlYW1MaW5lKGNvb3JkaW5hdGVzW2ldLCBzdHJlYW0sIDEpO1xuICBzdHJlYW0ucG9seWdvbkVuZCgpO1xufVxuXG52YXIgZ2VvU3RyZWFtID0gZnVuY3Rpb24ob2JqZWN0LCBzdHJlYW0pIHtcbiAgaWYgKG9iamVjdCAmJiBzdHJlYW1PYmplY3RUeXBlLmhhc093blByb3BlcnR5KG9iamVjdC50eXBlKSkge1xuICAgIHN0cmVhbU9iamVjdFR5cGVbb2JqZWN0LnR5cGVdKG9iamVjdCwgc3RyZWFtKTtcbiAgfSBlbHNlIHtcbiAgICBzdHJlYW1HZW9tZXRyeShvYmplY3QsIHN0cmVhbSk7XG4gIH1cbn07XG5cbnZhciBhcmVhUmluZ1N1bSA9IGFkZGVyKCk7XG5cbnZhciBhcmVhU3VtID0gYWRkZXIoKTtcbnZhciBsYW1iZGEwMDtcbnZhciBwaGkwMDtcbnZhciBsYW1iZGEwO1xudmFyIGNvc1BoaTA7XG52YXIgc2luUGhpMDtcblxudmFyIGFyZWFTdHJlYW0gPSB7XG4gIHBvaW50OiBub29wLFxuICBsaW5lU3RhcnQ6IG5vb3AsXG4gIGxpbmVFbmQ6IG5vb3AsXG4gIHBvbHlnb25TdGFydDogZnVuY3Rpb24oKSB7XG4gICAgYXJlYVJpbmdTdW0ucmVzZXQoKTtcbiAgICBhcmVhU3RyZWFtLmxpbmVTdGFydCA9IGFyZWFSaW5nU3RhcnQ7XG4gICAgYXJlYVN0cmVhbS5saW5lRW5kID0gYXJlYVJpbmdFbmQ7XG4gIH0sXG4gIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmVhUmluZyA9ICthcmVhUmluZ1N1bTtcbiAgICBhcmVhU3VtLmFkZChhcmVhUmluZyA8IDAgPyB0YXUgKyBhcmVhUmluZyA6IGFyZWFSaW5nKTtcbiAgICB0aGlzLmxpbmVTdGFydCA9IHRoaXMubGluZUVuZCA9IHRoaXMucG9pbnQgPSBub29wO1xuICB9LFxuICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgIGFyZWFTdW0uYWRkKHRhdSk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGFyZWFSaW5nU3RhcnQoKSB7XG4gIGFyZWFTdHJlYW0ucG9pbnQgPSBhcmVhUG9pbnRGaXJzdDtcbn1cblxuZnVuY3Rpb24gYXJlYVJpbmdFbmQoKSB7XG4gIGFyZWFQb2ludChsYW1iZGEwMCwgcGhpMDApO1xufVxuXG5mdW5jdGlvbiBhcmVhUG9pbnRGaXJzdChsYW1iZGEsIHBoaSkge1xuICBhcmVhU3RyZWFtLnBvaW50ID0gYXJlYVBvaW50O1xuICBsYW1iZGEwMCA9IGxhbWJkYSwgcGhpMDAgPSBwaGk7XG4gIGxhbWJkYSAqPSByYWRpYW5zLCBwaGkgKj0gcmFkaWFucztcbiAgbGFtYmRhMCA9IGxhbWJkYSwgY29zUGhpMCA9IGNvcyhwaGkgPSBwaGkgLyAyICsgcXVhcnRlclBpKSwgc2luUGhpMCA9IHNpbihwaGkpO1xufVxuXG5mdW5jdGlvbiBhcmVhUG9pbnQobGFtYmRhLCBwaGkpIHtcbiAgbGFtYmRhICo9IHJhZGlhbnMsIHBoaSAqPSByYWRpYW5zO1xuICBwaGkgPSBwaGkgLyAyICsgcXVhcnRlclBpOyAvLyBoYWxmIHRoZSBhbmd1bGFyIGRpc3RhbmNlIGZyb20gc291dGggcG9sZVxuXG4gIC8vIFNwaGVyaWNhbCBleGNlc3MgRSBmb3IgYSBzcGhlcmljYWwgdHJpYW5nbGUgd2l0aCB2ZXJ0aWNlczogc291dGggcG9sZSxcbiAgLy8gcHJldmlvdXMgcG9pbnQsIGN1cnJlbnQgcG9pbnQuICBVc2VzIGEgZm9ybXVsYSBkZXJpdmVkIGZyb20gQ2Fnbm9saeKAmXNcbiAgLy8gdGhlb3JlbS4gIFNlZSBUb2RodW50ZXIsIFNwaGVyaWNhbCBUcmlnLiAoMTg3MSksIFNlYy4gMTAzLCBFcS4gKDIpLlxuICB2YXIgZExhbWJkYSA9IGxhbWJkYSAtIGxhbWJkYTAsXG4gICAgICBzZExhbWJkYSA9IGRMYW1iZGEgPj0gMCA/IDEgOiAtMSxcbiAgICAgIGFkTGFtYmRhID0gc2RMYW1iZGEgKiBkTGFtYmRhLFxuICAgICAgY29zUGhpID0gY29zKHBoaSksXG4gICAgICBzaW5QaGkgPSBzaW4ocGhpKSxcbiAgICAgIGsgPSBzaW5QaGkwICogc2luUGhpLFxuICAgICAgdSA9IGNvc1BoaTAgKiBjb3NQaGkgKyBrICogY29zKGFkTGFtYmRhKSxcbiAgICAgIHYgPSBrICogc2RMYW1iZGEgKiBzaW4oYWRMYW1iZGEpO1xuICBhcmVhUmluZ1N1bS5hZGQoYXRhbjIodiwgdSkpO1xuXG4gIC8vIEFkdmFuY2UgdGhlIHByZXZpb3VzIHBvaW50cy5cbiAgbGFtYmRhMCA9IGxhbWJkYSwgY29zUGhpMCA9IGNvc1BoaSwgc2luUGhpMCA9IHNpblBoaTtcbn1cblxudmFyIGFyZWEgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgYXJlYVN1bS5yZXNldCgpO1xuICBnZW9TdHJlYW0ob2JqZWN0LCBhcmVhU3RyZWFtKTtcbiAgcmV0dXJuIGFyZWFTdW0gKiAyO1xufTtcblxuZnVuY3Rpb24gc3BoZXJpY2FsKGNhcnRlc2lhbikge1xuICByZXR1cm4gW2F0YW4yKGNhcnRlc2lhblsxXSwgY2FydGVzaWFuWzBdKSwgYXNpbihjYXJ0ZXNpYW5bMl0pXTtcbn1cblxuZnVuY3Rpb24gY2FydGVzaWFuKHNwaGVyaWNhbCkge1xuICB2YXIgbGFtYmRhID0gc3BoZXJpY2FsWzBdLCBwaGkgPSBzcGhlcmljYWxbMV0sIGNvc1BoaSA9IGNvcyhwaGkpO1xuICByZXR1cm4gW2Nvc1BoaSAqIGNvcyhsYW1iZGEpLCBjb3NQaGkgKiBzaW4obGFtYmRhKSwgc2luKHBoaSldO1xufVxuXG5mdW5jdGlvbiBjYXJ0ZXNpYW5Eb3QoYSwgYikge1xuICByZXR1cm4gYVswXSAqIGJbMF0gKyBhWzFdICogYlsxXSArIGFbMl0gKiBiWzJdO1xufVxuXG5mdW5jdGlvbiBjYXJ0ZXNpYW5Dcm9zcyhhLCBiKSB7XG4gIHJldHVybiBbYVsxXSAqIGJbMl0gLSBhWzJdICogYlsxXSwgYVsyXSAqIGJbMF0gLSBhWzBdICogYlsyXSwgYVswXSAqIGJbMV0gLSBhWzFdICogYlswXV07XG59XG5cbi8vIFRPRE8gcmV0dXJuIGFcbmZ1bmN0aW9uIGNhcnRlc2lhbkFkZEluUGxhY2UoYSwgYikge1xuICBhWzBdICs9IGJbMF0sIGFbMV0gKz0gYlsxXSwgYVsyXSArPSBiWzJdO1xufVxuXG5mdW5jdGlvbiBjYXJ0ZXNpYW5TY2FsZSh2ZWN0b3IsIGspIHtcbiAgcmV0dXJuIFt2ZWN0b3JbMF0gKiBrLCB2ZWN0b3JbMV0gKiBrLCB2ZWN0b3JbMl0gKiBrXTtcbn1cblxuLy8gVE9ETyByZXR1cm4gZFxuZnVuY3Rpb24gY2FydGVzaWFuTm9ybWFsaXplSW5QbGFjZShkKSB7XG4gIHZhciBsID0gc3FydChkWzBdICogZFswXSArIGRbMV0gKiBkWzFdICsgZFsyXSAqIGRbMl0pO1xuICBkWzBdIC89IGwsIGRbMV0gLz0gbCwgZFsyXSAvPSBsO1xufVxuXG52YXIgbGFtYmRhMCQxO1xudmFyIHBoaTA7XG52YXIgbGFtYmRhMTtcbnZhciBwaGkxO1xudmFyIGxhbWJkYTI7XG52YXIgbGFtYmRhMDAkMTtcbnZhciBwaGkwMCQxO1xudmFyIHAwO1xudmFyIGRlbHRhU3VtID0gYWRkZXIoKTtcbnZhciByYW5nZXM7XG52YXIgcmFuZ2UkMTtcblxudmFyIGJvdW5kc1N0cmVhbSA9IHtcbiAgcG9pbnQ6IGJvdW5kc1BvaW50LFxuICBsaW5lU3RhcnQ6IGJvdW5kc0xpbmVTdGFydCxcbiAgbGluZUVuZDogYm91bmRzTGluZUVuZCxcbiAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICBib3VuZHNTdHJlYW0ucG9pbnQgPSBib3VuZHNSaW5nUG9pbnQ7XG4gICAgYm91bmRzU3RyZWFtLmxpbmVTdGFydCA9IGJvdW5kc1JpbmdTdGFydDtcbiAgICBib3VuZHNTdHJlYW0ubGluZUVuZCA9IGJvdW5kc1JpbmdFbmQ7XG4gICAgZGVsdGFTdW0ucmVzZXQoKTtcbiAgICBhcmVhU3RyZWFtLnBvbHlnb25TdGFydCgpO1xuICB9LFxuICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICBhcmVhU3RyZWFtLnBvbHlnb25FbmQoKTtcbiAgICBib3VuZHNTdHJlYW0ucG9pbnQgPSBib3VuZHNQb2ludDtcbiAgICBib3VuZHNTdHJlYW0ubGluZVN0YXJ0ID0gYm91bmRzTGluZVN0YXJ0O1xuICAgIGJvdW5kc1N0cmVhbS5saW5lRW5kID0gYm91bmRzTGluZUVuZDtcbiAgICBpZiAoYXJlYVJpbmdTdW0gPCAwKSBsYW1iZGEwJDEgPSAtKGxhbWJkYTEgPSAxODApLCBwaGkwID0gLShwaGkxID0gOTApO1xuICAgIGVsc2UgaWYgKGRlbHRhU3VtID4gZXBzaWxvbikgcGhpMSA9IDkwO1xuICAgIGVsc2UgaWYgKGRlbHRhU3VtIDwgLWVwc2lsb24pIHBoaTAgPSAtOTA7XG4gICAgcmFuZ2UkMVswXSA9IGxhbWJkYTAkMSwgcmFuZ2UkMVsxXSA9IGxhbWJkYTE7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGJvdW5kc1BvaW50KGxhbWJkYSwgcGhpKSB7XG4gIHJhbmdlcy5wdXNoKHJhbmdlJDEgPSBbbGFtYmRhMCQxID0gbGFtYmRhLCBsYW1iZGExID0gbGFtYmRhXSk7XG4gIGlmIChwaGkgPCBwaGkwKSBwaGkwID0gcGhpO1xuICBpZiAocGhpID4gcGhpMSkgcGhpMSA9IHBoaTtcbn1cblxuZnVuY3Rpb24gbGluZVBvaW50KGxhbWJkYSwgcGhpKSB7XG4gIHZhciBwID0gY2FydGVzaWFuKFtsYW1iZGEgKiByYWRpYW5zLCBwaGkgKiByYWRpYW5zXSk7XG4gIGlmIChwMCkge1xuICAgIHZhciBub3JtYWwgPSBjYXJ0ZXNpYW5Dcm9zcyhwMCwgcCksXG4gICAgICAgIGVxdWF0b3JpYWwgPSBbbm9ybWFsWzFdLCAtbm9ybWFsWzBdLCAwXSxcbiAgICAgICAgaW5mbGVjdGlvbiA9IGNhcnRlc2lhbkNyb3NzKGVxdWF0b3JpYWwsIG5vcm1hbCk7XG4gICAgY2FydGVzaWFuTm9ybWFsaXplSW5QbGFjZShpbmZsZWN0aW9uKTtcbiAgICBpbmZsZWN0aW9uID0gc3BoZXJpY2FsKGluZmxlY3Rpb24pO1xuICAgIHZhciBkZWx0YSA9IGxhbWJkYSAtIGxhbWJkYTIsXG4gICAgICAgIHNpZ24kJDEgPSBkZWx0YSA+IDAgPyAxIDogLTEsXG4gICAgICAgIGxhbWJkYWkgPSBpbmZsZWN0aW9uWzBdICogZGVncmVlcyAqIHNpZ24kJDEsXG4gICAgICAgIHBoaWksXG4gICAgICAgIGFudGltZXJpZGlhbiA9IGFicyhkZWx0YSkgPiAxODA7XG4gICAgaWYgKGFudGltZXJpZGlhbiBeIChzaWduJCQxICogbGFtYmRhMiA8IGxhbWJkYWkgJiYgbGFtYmRhaSA8IHNpZ24kJDEgKiBsYW1iZGEpKSB7XG4gICAgICBwaGlpID0gaW5mbGVjdGlvblsxXSAqIGRlZ3JlZXM7XG4gICAgICBpZiAocGhpaSA+IHBoaTEpIHBoaTEgPSBwaGlpO1xuICAgIH0gZWxzZSBpZiAobGFtYmRhaSA9IChsYW1iZGFpICsgMzYwKSAlIDM2MCAtIDE4MCwgYW50aW1lcmlkaWFuIF4gKHNpZ24kJDEgKiBsYW1iZGEyIDwgbGFtYmRhaSAmJiBsYW1iZGFpIDwgc2lnbiQkMSAqIGxhbWJkYSkpIHtcbiAgICAgIHBoaWkgPSAtaW5mbGVjdGlvblsxXSAqIGRlZ3JlZXM7XG4gICAgICBpZiAocGhpaSA8IHBoaTApIHBoaTAgPSBwaGlpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocGhpIDwgcGhpMCkgcGhpMCA9IHBoaTtcbiAgICAgIGlmIChwaGkgPiBwaGkxKSBwaGkxID0gcGhpO1xuICAgIH1cbiAgICBpZiAoYW50aW1lcmlkaWFuKSB7XG4gICAgICBpZiAobGFtYmRhIDwgbGFtYmRhMikge1xuICAgICAgICBpZiAoYW5nbGUobGFtYmRhMCQxLCBsYW1iZGEpID4gYW5nbGUobGFtYmRhMCQxLCBsYW1iZGExKSkgbGFtYmRhMSA9IGxhbWJkYTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChhbmdsZShsYW1iZGEsIGxhbWJkYTEpID4gYW5nbGUobGFtYmRhMCQxLCBsYW1iZGExKSkgbGFtYmRhMCQxID0gbGFtYmRhO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAobGFtYmRhMSA+PSBsYW1iZGEwJDEpIHtcbiAgICAgICAgaWYgKGxhbWJkYSA8IGxhbWJkYTAkMSkgbGFtYmRhMCQxID0gbGFtYmRhO1xuICAgICAgICBpZiAobGFtYmRhID4gbGFtYmRhMSkgbGFtYmRhMSA9IGxhbWJkYTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChsYW1iZGEgPiBsYW1iZGEyKSB7XG4gICAgICAgICAgaWYgKGFuZ2xlKGxhbWJkYTAkMSwgbGFtYmRhKSA+IGFuZ2xlKGxhbWJkYTAkMSwgbGFtYmRhMSkpIGxhbWJkYTEgPSBsYW1iZGE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGFuZ2xlKGxhbWJkYSwgbGFtYmRhMSkgPiBhbmdsZShsYW1iZGEwJDEsIGxhbWJkYTEpKSBsYW1iZGEwJDEgPSBsYW1iZGE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmFuZ2VzLnB1c2gocmFuZ2UkMSA9IFtsYW1iZGEwJDEgPSBsYW1iZGEsIGxhbWJkYTEgPSBsYW1iZGFdKTtcbiAgfVxuICBpZiAocGhpIDwgcGhpMCkgcGhpMCA9IHBoaTtcbiAgaWYgKHBoaSA+IHBoaTEpIHBoaTEgPSBwaGk7XG4gIHAwID0gcCwgbGFtYmRhMiA9IGxhbWJkYTtcbn1cblxuZnVuY3Rpb24gYm91bmRzTGluZVN0YXJ0KCkge1xuICBib3VuZHNTdHJlYW0ucG9pbnQgPSBsaW5lUG9pbnQ7XG59XG5cbmZ1bmN0aW9uIGJvdW5kc0xpbmVFbmQoKSB7XG4gIHJhbmdlJDFbMF0gPSBsYW1iZGEwJDEsIHJhbmdlJDFbMV0gPSBsYW1iZGExO1xuICBib3VuZHNTdHJlYW0ucG9pbnQgPSBib3VuZHNQb2ludDtcbiAgcDAgPSBudWxsO1xufVxuXG5mdW5jdGlvbiBib3VuZHNSaW5nUG9pbnQobGFtYmRhLCBwaGkpIHtcbiAgaWYgKHAwKSB7XG4gICAgdmFyIGRlbHRhID0gbGFtYmRhIC0gbGFtYmRhMjtcbiAgICBkZWx0YVN1bS5hZGQoYWJzKGRlbHRhKSA+IDE4MCA/IGRlbHRhICsgKGRlbHRhID4gMCA/IDM2MCA6IC0zNjApIDogZGVsdGEpO1xuICB9IGVsc2Uge1xuICAgIGxhbWJkYTAwJDEgPSBsYW1iZGEsIHBoaTAwJDEgPSBwaGk7XG4gIH1cbiAgYXJlYVN0cmVhbS5wb2ludChsYW1iZGEsIHBoaSk7XG4gIGxpbmVQb2ludChsYW1iZGEsIHBoaSk7XG59XG5cbmZ1bmN0aW9uIGJvdW5kc1JpbmdTdGFydCgpIHtcbiAgYXJlYVN0cmVhbS5saW5lU3RhcnQoKTtcbn1cblxuZnVuY3Rpb24gYm91bmRzUmluZ0VuZCgpIHtcbiAgYm91bmRzUmluZ1BvaW50KGxhbWJkYTAwJDEsIHBoaTAwJDEpO1xuICBhcmVhU3RyZWFtLmxpbmVFbmQoKTtcbiAgaWYgKGFicyhkZWx0YVN1bSkgPiBlcHNpbG9uKSBsYW1iZGEwJDEgPSAtKGxhbWJkYTEgPSAxODApO1xuICByYW5nZSQxWzBdID0gbGFtYmRhMCQxLCByYW5nZSQxWzFdID0gbGFtYmRhMTtcbiAgcDAgPSBudWxsO1xufVxuXG4vLyBGaW5kcyB0aGUgbGVmdC1yaWdodCBkaXN0YW5jZSBiZXR3ZWVuIHR3byBsb25naXR1ZGVzLlxuLy8gVGhpcyBpcyBhbG1vc3QgdGhlIHNhbWUgYXMgKGxhbWJkYTEgLSBsYW1iZGEwICsgMzYwwrApICUgMzYwwrAsIGV4Y2VwdCB0aGF0IHdlIHdhbnRcbi8vIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIMKxMTgwwrAgdG8gYmUgMzYwwrAuXG5mdW5jdGlvbiBhbmdsZShsYW1iZGEwLCBsYW1iZGExKSB7XG4gIHJldHVybiAobGFtYmRhMSAtPSBsYW1iZGEwKSA8IDAgPyBsYW1iZGExICsgMzYwIDogbGFtYmRhMTtcbn1cblxuZnVuY3Rpb24gcmFuZ2VDb21wYXJlKGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gLSBiWzBdO1xufVxuXG5mdW5jdGlvbiByYW5nZUNvbnRhaW5zKHJhbmdlJCQxLCB4KSB7XG4gIHJldHVybiByYW5nZSQkMVswXSA8PSByYW5nZSQkMVsxXSA/IHJhbmdlJCQxWzBdIDw9IHggJiYgeCA8PSByYW5nZSQkMVsxXSA6IHggPCByYW5nZSQkMVswXSB8fCByYW5nZSQkMVsxXSA8IHg7XG59XG5cbnZhciBib3VuZHMgPSBmdW5jdGlvbihmZWF0dXJlKSB7XG4gIHZhciBpLCBuLCBhLCBiLCBtZXJnZWQsIGRlbHRhTWF4LCBkZWx0YTtcblxuICBwaGkxID0gbGFtYmRhMSA9IC0obGFtYmRhMCQxID0gcGhpMCA9IEluZmluaXR5KTtcbiAgcmFuZ2VzID0gW107XG4gIGdlb1N0cmVhbShmZWF0dXJlLCBib3VuZHNTdHJlYW0pO1xuXG4gIC8vIEZpcnN0LCBzb3J0IHJhbmdlcyBieSB0aGVpciBtaW5pbXVtIGxvbmdpdHVkZXMuXG4gIGlmIChuID0gcmFuZ2VzLmxlbmd0aCkge1xuICAgIHJhbmdlcy5zb3J0KHJhbmdlQ29tcGFyZSk7XG5cbiAgICAvLyBUaGVuLCBtZXJnZSBhbnkgcmFuZ2VzIHRoYXQgb3ZlcmxhcC5cbiAgICBmb3IgKGkgPSAxLCBhID0gcmFuZ2VzWzBdLCBtZXJnZWQgPSBbYV07IGkgPCBuOyArK2kpIHtcbiAgICAgIGIgPSByYW5nZXNbaV07XG4gICAgICBpZiAocmFuZ2VDb250YWlucyhhLCBiWzBdKSB8fCByYW5nZUNvbnRhaW5zKGEsIGJbMV0pKSB7XG4gICAgICAgIGlmIChhbmdsZShhWzBdLCBiWzFdKSA+IGFuZ2xlKGFbMF0sIGFbMV0pKSBhWzFdID0gYlsxXTtcbiAgICAgICAgaWYgKGFuZ2xlKGJbMF0sIGFbMV0pID4gYW5nbGUoYVswXSwgYVsxXSkpIGFbMF0gPSBiWzBdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWVyZ2VkLnB1c2goYSA9IGIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEZpbmFsbHksIGZpbmQgdGhlIGxhcmdlc3QgZ2FwIGJldHdlZW4gdGhlIG1lcmdlZCByYW5nZXMuXG4gICAgLy8gVGhlIGZpbmFsIGJvdW5kaW5nIGJveCB3aWxsIGJlIHRoZSBpbnZlcnNlIG9mIHRoaXMgZ2FwLlxuICAgIGZvciAoZGVsdGFNYXggPSAtSW5maW5pdHksIG4gPSBtZXJnZWQubGVuZ3RoIC0gMSwgaSA9IDAsIGEgPSBtZXJnZWRbbl07IGkgPD0gbjsgYSA9IGIsICsraSkge1xuICAgICAgYiA9IG1lcmdlZFtpXTtcbiAgICAgIGlmICgoZGVsdGEgPSBhbmdsZShhWzFdLCBiWzBdKSkgPiBkZWx0YU1heCkgZGVsdGFNYXggPSBkZWx0YSwgbGFtYmRhMCQxID0gYlswXSwgbGFtYmRhMSA9IGFbMV07XG4gICAgfVxuICB9XG5cbiAgcmFuZ2VzID0gcmFuZ2UkMSA9IG51bGw7XG5cbiAgcmV0dXJuIGxhbWJkYTAkMSA9PT0gSW5maW5pdHkgfHwgcGhpMCA9PT0gSW5maW5pdHlcbiAgICAgID8gW1tOYU4sIE5hTl0sIFtOYU4sIE5hTl1dXG4gICAgICA6IFtbbGFtYmRhMCQxLCBwaGkwXSwgW2xhbWJkYTEsIHBoaTFdXTtcbn07XG5cbnZhciBXMDtcbnZhciBXMTtcbnZhciBYMDtcbnZhciBZMDtcbnZhciBaMDtcbnZhciBYMTtcbnZhciBZMTtcbnZhciBaMTtcbnZhciBYMjtcbnZhciBZMjtcbnZhciBaMjtcbnZhciBsYW1iZGEwMCQyO1xudmFyIHBoaTAwJDI7XG52YXIgeDA7XG52YXIgeTA7XG52YXIgejA7IC8vIHByZXZpb3VzIHBvaW50XG5cbnZhciBjZW50cm9pZFN0cmVhbSA9IHtcbiAgc3BoZXJlOiBub29wLFxuICBwb2ludDogY2VudHJvaWRQb2ludCxcbiAgbGluZVN0YXJ0OiBjZW50cm9pZExpbmVTdGFydCxcbiAgbGluZUVuZDogY2VudHJvaWRMaW5lRW5kLFxuICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIGNlbnRyb2lkU3RyZWFtLmxpbmVTdGFydCA9IGNlbnRyb2lkUmluZ1N0YXJ0O1xuICAgIGNlbnRyb2lkU3RyZWFtLmxpbmVFbmQgPSBjZW50cm9pZFJpbmdFbmQ7XG4gIH0sXG4gIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkge1xuICAgIGNlbnRyb2lkU3RyZWFtLmxpbmVTdGFydCA9IGNlbnRyb2lkTGluZVN0YXJ0O1xuICAgIGNlbnRyb2lkU3RyZWFtLmxpbmVFbmQgPSBjZW50cm9pZExpbmVFbmQ7XG4gIH1cbn07XG5cbi8vIEFyaXRobWV0aWMgbWVhbiBvZiBDYXJ0ZXNpYW4gdmVjdG9ycy5cbmZ1bmN0aW9uIGNlbnRyb2lkUG9pbnQobGFtYmRhLCBwaGkpIHtcbiAgbGFtYmRhICo9IHJhZGlhbnMsIHBoaSAqPSByYWRpYW5zO1xuICB2YXIgY29zUGhpID0gY29zKHBoaSk7XG4gIGNlbnRyb2lkUG9pbnRDYXJ0ZXNpYW4oY29zUGhpICogY29zKGxhbWJkYSksIGNvc1BoaSAqIHNpbihsYW1iZGEpLCBzaW4ocGhpKSk7XG59XG5cbmZ1bmN0aW9uIGNlbnRyb2lkUG9pbnRDYXJ0ZXNpYW4oeCwgeSwgeikge1xuICArK1cwO1xuICBYMCArPSAoeCAtIFgwKSAvIFcwO1xuICBZMCArPSAoeSAtIFkwKSAvIFcwO1xuICBaMCArPSAoeiAtIFowKSAvIFcwO1xufVxuXG5mdW5jdGlvbiBjZW50cm9pZExpbmVTdGFydCgpIHtcbiAgY2VudHJvaWRTdHJlYW0ucG9pbnQgPSBjZW50cm9pZExpbmVQb2ludEZpcnN0O1xufVxuXG5mdW5jdGlvbiBjZW50cm9pZExpbmVQb2ludEZpcnN0KGxhbWJkYSwgcGhpKSB7XG4gIGxhbWJkYSAqPSByYWRpYW5zLCBwaGkgKj0gcmFkaWFucztcbiAgdmFyIGNvc1BoaSA9IGNvcyhwaGkpO1xuICB4MCA9IGNvc1BoaSAqIGNvcyhsYW1iZGEpO1xuICB5MCA9IGNvc1BoaSAqIHNpbihsYW1iZGEpO1xuICB6MCA9IHNpbihwaGkpO1xuICBjZW50cm9pZFN0cmVhbS5wb2ludCA9IGNlbnRyb2lkTGluZVBvaW50O1xuICBjZW50cm9pZFBvaW50Q2FydGVzaWFuKHgwLCB5MCwgejApO1xufVxuXG5mdW5jdGlvbiBjZW50cm9pZExpbmVQb2ludChsYW1iZGEsIHBoaSkge1xuICBsYW1iZGEgKj0gcmFkaWFucywgcGhpICo9IHJhZGlhbnM7XG4gIHZhciBjb3NQaGkgPSBjb3MocGhpKSxcbiAgICAgIHggPSBjb3NQaGkgKiBjb3MobGFtYmRhKSxcbiAgICAgIHkgPSBjb3NQaGkgKiBzaW4obGFtYmRhKSxcbiAgICAgIHogPSBzaW4ocGhpKSxcbiAgICAgIHcgPSBhdGFuMihzcXJ0KCh3ID0geTAgKiB6IC0gejAgKiB5KSAqIHcgKyAodyA9IHowICogeCAtIHgwICogeikgKiB3ICsgKHcgPSB4MCAqIHkgLSB5MCAqIHgpICogdyksIHgwICogeCArIHkwICogeSArIHowICogeik7XG4gIFcxICs9IHc7XG4gIFgxICs9IHcgKiAoeDAgKyAoeDAgPSB4KSk7XG4gIFkxICs9IHcgKiAoeTAgKyAoeTAgPSB5KSk7XG4gIFoxICs9IHcgKiAoejAgKyAoejAgPSB6KSk7XG4gIGNlbnRyb2lkUG9pbnRDYXJ0ZXNpYW4oeDAsIHkwLCB6MCk7XG59XG5cbmZ1bmN0aW9uIGNlbnRyb2lkTGluZUVuZCgpIHtcbiAgY2VudHJvaWRTdHJlYW0ucG9pbnQgPSBjZW50cm9pZFBvaW50O1xufVxuXG4vLyBTZWUgSi4gRS4gQnJvY2ssIFRoZSBJbmVydGlhIFRlbnNvciBmb3IgYSBTcGhlcmljYWwgVHJpYW5nbGUsXG4vLyBKLiBBcHBsaWVkIE1lY2hhbmljcyA0MiwgMjM5ICgxOTc1KS5cbmZ1bmN0aW9uIGNlbnRyb2lkUmluZ1N0YXJ0KCkge1xuICBjZW50cm9pZFN0cmVhbS5wb2ludCA9IGNlbnRyb2lkUmluZ1BvaW50Rmlyc3Q7XG59XG5cbmZ1bmN0aW9uIGNlbnRyb2lkUmluZ0VuZCgpIHtcbiAgY2VudHJvaWRSaW5nUG9pbnQobGFtYmRhMDAkMiwgcGhpMDAkMik7XG4gIGNlbnRyb2lkU3RyZWFtLnBvaW50ID0gY2VudHJvaWRQb2ludDtcbn1cblxuZnVuY3Rpb24gY2VudHJvaWRSaW5nUG9pbnRGaXJzdChsYW1iZGEsIHBoaSkge1xuICBsYW1iZGEwMCQyID0gbGFtYmRhLCBwaGkwMCQyID0gcGhpO1xuICBsYW1iZGEgKj0gcmFkaWFucywgcGhpICo9IHJhZGlhbnM7XG4gIGNlbnRyb2lkU3RyZWFtLnBvaW50ID0gY2VudHJvaWRSaW5nUG9pbnQ7XG4gIHZhciBjb3NQaGkgPSBjb3MocGhpKTtcbiAgeDAgPSBjb3NQaGkgKiBjb3MobGFtYmRhKTtcbiAgeTAgPSBjb3NQaGkgKiBzaW4obGFtYmRhKTtcbiAgejAgPSBzaW4ocGhpKTtcbiAgY2VudHJvaWRQb2ludENhcnRlc2lhbih4MCwgeTAsIHowKTtcbn1cblxuZnVuY3Rpb24gY2VudHJvaWRSaW5nUG9pbnQobGFtYmRhLCBwaGkpIHtcbiAgbGFtYmRhICo9IHJhZGlhbnMsIHBoaSAqPSByYWRpYW5zO1xuICB2YXIgY29zUGhpID0gY29zKHBoaSksXG4gICAgICB4ID0gY29zUGhpICogY29zKGxhbWJkYSksXG4gICAgICB5ID0gY29zUGhpICogc2luKGxhbWJkYSksXG4gICAgICB6ID0gc2luKHBoaSksXG4gICAgICBjeCA9IHkwICogeiAtIHowICogeSxcbiAgICAgIGN5ID0gejAgKiB4IC0geDAgKiB6LFxuICAgICAgY3ogPSB4MCAqIHkgLSB5MCAqIHgsXG4gICAgICBtID0gc3FydChjeCAqIGN4ICsgY3kgKiBjeSArIGN6ICogY3opLFxuICAgICAgdyA9IGFzaW4obSksIC8vIGxpbmUgd2VpZ2h0ID0gYW5nbGVcbiAgICAgIHYgPSBtICYmIC13IC8gbTsgLy8gYXJlYSB3ZWlnaHQgbXVsdGlwbGllclxuICBYMiArPSB2ICogY3g7XG4gIFkyICs9IHYgKiBjeTtcbiAgWjIgKz0gdiAqIGN6O1xuICBXMSArPSB3O1xuICBYMSArPSB3ICogKHgwICsgKHgwID0geCkpO1xuICBZMSArPSB3ICogKHkwICsgKHkwID0geSkpO1xuICBaMSArPSB3ICogKHowICsgKHowID0geikpO1xuICBjZW50cm9pZFBvaW50Q2FydGVzaWFuKHgwLCB5MCwgejApO1xufVxuXG52YXIgY2VudHJvaWQgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgVzAgPSBXMSA9XG4gIFgwID0gWTAgPSBaMCA9XG4gIFgxID0gWTEgPSBaMSA9XG4gIFgyID0gWTIgPSBaMiA9IDA7XG4gIGdlb1N0cmVhbShvYmplY3QsIGNlbnRyb2lkU3RyZWFtKTtcblxuICB2YXIgeCA9IFgyLFxuICAgICAgeSA9IFkyLFxuICAgICAgeiA9IFoyLFxuICAgICAgbSA9IHggKiB4ICsgeSAqIHkgKyB6ICogejtcblxuICAvLyBJZiB0aGUgYXJlYS13ZWlnaHRlZCBjY2VudHJvaWQgaXMgdW5kZWZpbmVkLCBmYWxsIGJhY2sgdG8gbGVuZ3RoLXdlaWdodGVkIGNjZW50cm9pZC5cbiAgaWYgKG0gPCBlcHNpbG9uMikge1xuICAgIHggPSBYMSwgeSA9IFkxLCB6ID0gWjE7XG4gICAgLy8gSWYgdGhlIGZlYXR1cmUgaGFzIHplcm8gbGVuZ3RoLCBmYWxsIGJhY2sgdG8gYXJpdGhtZXRpYyBtZWFuIG9mIHBvaW50IHZlY3RvcnMuXG4gICAgaWYgKFcxIDwgZXBzaWxvbikgeCA9IFgwLCB5ID0gWTAsIHogPSBaMDtcbiAgICBtID0geCAqIHggKyB5ICogeSArIHogKiB6O1xuICAgIC8vIElmIHRoZSBmZWF0dXJlIHN0aWxsIGhhcyBhbiB1bmRlZmluZWQgY2NlbnRyb2lkLCB0aGVuIHJldHVybi5cbiAgICBpZiAobSA8IGVwc2lsb24yKSByZXR1cm4gW05hTiwgTmFOXTtcbiAgfVxuXG4gIHJldHVybiBbYXRhbjIoeSwgeCkgKiBkZWdyZWVzLCBhc2luKHogLyBzcXJ0KG0pKSAqIGRlZ3JlZXNdO1xufTtcblxudmFyIGNvbnN0YW50ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59O1xuXG52YXIgY29tcG9zZSA9IGZ1bmN0aW9uKGEsIGIpIHtcblxuICBmdW5jdGlvbiBjb21wb3NlKHgsIHkpIHtcbiAgICByZXR1cm4geCA9IGEoeCwgeSksIGIoeFswXSwgeFsxXSk7XG4gIH1cblxuICBpZiAoYS5pbnZlcnQgJiYgYi5pbnZlcnQpIGNvbXBvc2UuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHJldHVybiB4ID0gYi5pbnZlcnQoeCwgeSksIHggJiYgYS5pbnZlcnQoeFswXSwgeFsxXSk7XG4gIH07XG5cbiAgcmV0dXJuIGNvbXBvc2U7XG59O1xuXG5mdW5jdGlvbiByb3RhdGlvbklkZW50aXR5KGxhbWJkYSwgcGhpKSB7XG4gIHJldHVybiBbbGFtYmRhID4gcGkgPyBsYW1iZGEgLSB0YXUgOiBsYW1iZGEgPCAtcGkgPyBsYW1iZGEgKyB0YXUgOiBsYW1iZGEsIHBoaV07XG59XG5cbnJvdGF0aW9uSWRlbnRpdHkuaW52ZXJ0ID0gcm90YXRpb25JZGVudGl0eTtcblxuZnVuY3Rpb24gcm90YXRlUmFkaWFucyhkZWx0YUxhbWJkYSwgZGVsdGFQaGksIGRlbHRhR2FtbWEpIHtcbiAgcmV0dXJuIChkZWx0YUxhbWJkYSAlPSB0YXUpID8gKGRlbHRhUGhpIHx8IGRlbHRhR2FtbWEgPyBjb21wb3NlKHJvdGF0aW9uTGFtYmRhKGRlbHRhTGFtYmRhKSwgcm90YXRpb25QaGlHYW1tYShkZWx0YVBoaSwgZGVsdGFHYW1tYSkpXG4gICAgOiByb3RhdGlvbkxhbWJkYShkZWx0YUxhbWJkYSkpXG4gICAgOiAoZGVsdGFQaGkgfHwgZGVsdGFHYW1tYSA/IHJvdGF0aW9uUGhpR2FtbWEoZGVsdGFQaGksIGRlbHRhR2FtbWEpXG4gICAgOiByb3RhdGlvbklkZW50aXR5KTtcbn1cblxuZnVuY3Rpb24gZm9yd2FyZFJvdGF0aW9uTGFtYmRhKGRlbHRhTGFtYmRhKSB7XG4gIHJldHVybiBmdW5jdGlvbihsYW1iZGEsIHBoaSkge1xuICAgIHJldHVybiBsYW1iZGEgKz0gZGVsdGFMYW1iZGEsIFtsYW1iZGEgPiBwaSA/IGxhbWJkYSAtIHRhdSA6IGxhbWJkYSA8IC1waSA/IGxhbWJkYSArIHRhdSA6IGxhbWJkYSwgcGhpXTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcm90YXRpb25MYW1iZGEoZGVsdGFMYW1iZGEpIHtcbiAgdmFyIHJvdGF0aW9uID0gZm9yd2FyZFJvdGF0aW9uTGFtYmRhKGRlbHRhTGFtYmRhKTtcbiAgcm90YXRpb24uaW52ZXJ0ID0gZm9yd2FyZFJvdGF0aW9uTGFtYmRhKC1kZWx0YUxhbWJkYSk7XG4gIHJldHVybiByb3RhdGlvbjtcbn1cblxuZnVuY3Rpb24gcm90YXRpb25QaGlHYW1tYShkZWx0YVBoaSwgZGVsdGFHYW1tYSkge1xuICB2YXIgY29zRGVsdGFQaGkgPSBjb3MoZGVsdGFQaGkpLFxuICAgICAgc2luRGVsdGFQaGkgPSBzaW4oZGVsdGFQaGkpLFxuICAgICAgY29zRGVsdGFHYW1tYSA9IGNvcyhkZWx0YUdhbW1hKSxcbiAgICAgIHNpbkRlbHRhR2FtbWEgPSBzaW4oZGVsdGFHYW1tYSk7XG5cbiAgZnVuY3Rpb24gcm90YXRpb24obGFtYmRhLCBwaGkpIHtcbiAgICB2YXIgY29zUGhpID0gY29zKHBoaSksXG4gICAgICAgIHggPSBjb3MobGFtYmRhKSAqIGNvc1BoaSxcbiAgICAgICAgeSA9IHNpbihsYW1iZGEpICogY29zUGhpLFxuICAgICAgICB6ID0gc2luKHBoaSksXG4gICAgICAgIGsgPSB6ICogY29zRGVsdGFQaGkgKyB4ICogc2luRGVsdGFQaGk7XG4gICAgcmV0dXJuIFtcbiAgICAgIGF0YW4yKHkgKiBjb3NEZWx0YUdhbW1hIC0gayAqIHNpbkRlbHRhR2FtbWEsIHggKiBjb3NEZWx0YVBoaSAtIHogKiBzaW5EZWx0YVBoaSksXG4gICAgICBhc2luKGsgKiBjb3NEZWx0YUdhbW1hICsgeSAqIHNpbkRlbHRhR2FtbWEpXG4gICAgXTtcbiAgfVxuXG4gIHJvdGF0aW9uLmludmVydCA9IGZ1bmN0aW9uKGxhbWJkYSwgcGhpKSB7XG4gICAgdmFyIGNvc1BoaSA9IGNvcyhwaGkpLFxuICAgICAgICB4ID0gY29zKGxhbWJkYSkgKiBjb3NQaGksXG4gICAgICAgIHkgPSBzaW4obGFtYmRhKSAqIGNvc1BoaSxcbiAgICAgICAgeiA9IHNpbihwaGkpLFxuICAgICAgICBrID0geiAqIGNvc0RlbHRhR2FtbWEgLSB5ICogc2luRGVsdGFHYW1tYTtcbiAgICByZXR1cm4gW1xuICAgICAgYXRhbjIoeSAqIGNvc0RlbHRhR2FtbWEgKyB6ICogc2luRGVsdGFHYW1tYSwgeCAqIGNvc0RlbHRhUGhpICsgayAqIHNpbkRlbHRhUGhpKSxcbiAgICAgIGFzaW4oayAqIGNvc0RlbHRhUGhpIC0geCAqIHNpbkRlbHRhUGhpKVxuICAgIF07XG4gIH07XG5cbiAgcmV0dXJuIHJvdGF0aW9uO1xufVxuXG52YXIgcm90YXRpb24gPSBmdW5jdGlvbihyb3RhdGUpIHtcbiAgcm90YXRlID0gcm90YXRlUmFkaWFucyhyb3RhdGVbMF0gKiByYWRpYW5zLCByb3RhdGVbMV0gKiByYWRpYW5zLCByb3RhdGUubGVuZ3RoID4gMiA/IHJvdGF0ZVsyXSAqIHJhZGlhbnMgOiAwKTtcblxuICBmdW5jdGlvbiBmb3J3YXJkKGNvb3JkaW5hdGVzKSB7XG4gICAgY29vcmRpbmF0ZXMgPSByb3RhdGUoY29vcmRpbmF0ZXNbMF0gKiByYWRpYW5zLCBjb29yZGluYXRlc1sxXSAqIHJhZGlhbnMpO1xuICAgIHJldHVybiBjb29yZGluYXRlc1swXSAqPSBkZWdyZWVzLCBjb29yZGluYXRlc1sxXSAqPSBkZWdyZWVzLCBjb29yZGluYXRlcztcbiAgfVxuXG4gIGZvcndhcmQuaW52ZXJ0ID0gZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHtcbiAgICBjb29yZGluYXRlcyA9IHJvdGF0ZS5pbnZlcnQoY29vcmRpbmF0ZXNbMF0gKiByYWRpYW5zLCBjb29yZGluYXRlc1sxXSAqIHJhZGlhbnMpO1xuICAgIHJldHVybiBjb29yZGluYXRlc1swXSAqPSBkZWdyZWVzLCBjb29yZGluYXRlc1sxXSAqPSBkZWdyZWVzLCBjb29yZGluYXRlcztcbiAgfTtcblxuICByZXR1cm4gZm9yd2FyZDtcbn07XG5cbi8vIEdlbmVyYXRlcyBhIGNpcmNsZSBjZW50ZXJlZCBhdCBbMMKwLCAwwrBdLCB3aXRoIGEgZ2l2ZW4gcmFkaXVzIGFuZCBwcmVjaXNpb24uXG5mdW5jdGlvbiBjaXJjbGVTdHJlYW0oc3RyZWFtLCByYWRpdXMsIGRlbHRhLCBkaXJlY3Rpb24sIHQwLCB0MSkge1xuICBpZiAoIWRlbHRhKSByZXR1cm47XG4gIHZhciBjb3NSYWRpdXMgPSBjb3MocmFkaXVzKSxcbiAgICAgIHNpblJhZGl1cyA9IHNpbihyYWRpdXMpLFxuICAgICAgc3RlcCA9IGRpcmVjdGlvbiAqIGRlbHRhO1xuICBpZiAodDAgPT0gbnVsbCkge1xuICAgIHQwID0gcmFkaXVzICsgZGlyZWN0aW9uICogdGF1O1xuICAgIHQxID0gcmFkaXVzIC0gc3RlcCAvIDI7XG4gIH0gZWxzZSB7XG4gICAgdDAgPSBjaXJjbGVSYWRpdXMoY29zUmFkaXVzLCB0MCk7XG4gICAgdDEgPSBjaXJjbGVSYWRpdXMoY29zUmFkaXVzLCB0MSk7XG4gICAgaWYgKGRpcmVjdGlvbiA+IDAgPyB0MCA8IHQxIDogdDAgPiB0MSkgdDAgKz0gZGlyZWN0aW9uICogdGF1O1xuICB9XG4gIGZvciAodmFyIHBvaW50LCB0ID0gdDA7IGRpcmVjdGlvbiA+IDAgPyB0ID4gdDEgOiB0IDwgdDE7IHQgLT0gc3RlcCkge1xuICAgIHBvaW50ID0gc3BoZXJpY2FsKFtjb3NSYWRpdXMsIC1zaW5SYWRpdXMgKiBjb3ModCksIC1zaW5SYWRpdXMgKiBzaW4odCldKTtcbiAgICBzdHJlYW0ucG9pbnQocG9pbnRbMF0sIHBvaW50WzFdKTtcbiAgfVxufVxuXG4vLyBSZXR1cm5zIHRoZSBzaWduZWQgYW5nbGUgb2YgYSBjYXJ0ZXNpYW4gcG9pbnQgcmVsYXRpdmUgdG8gW2Nvc1JhZGl1cywgMCwgMF0uXG5mdW5jdGlvbiBjaXJjbGVSYWRpdXMoY29zUmFkaXVzLCBwb2ludCkge1xuICBwb2ludCA9IGNhcnRlc2lhbihwb2ludCksIHBvaW50WzBdIC09IGNvc1JhZGl1cztcbiAgY2FydGVzaWFuTm9ybWFsaXplSW5QbGFjZShwb2ludCk7XG4gIHZhciByYWRpdXMgPSBhY29zKC1wb2ludFsxXSk7XG4gIHJldHVybiAoKC1wb2ludFsyXSA8IDAgPyAtcmFkaXVzIDogcmFkaXVzKSArIHRhdSAtIGVwc2lsb24pICUgdGF1O1xufVxuXG52YXIgY2lyY2xlID0gZnVuY3Rpb24oKSB7XG4gIHZhciBjZW50ZXIgPSBjb25zdGFudChbMCwgMF0pLFxuICAgICAgcmFkaXVzID0gY29uc3RhbnQoOTApLFxuICAgICAgcHJlY2lzaW9uID0gY29uc3RhbnQoNiksXG4gICAgICByaW5nLFxuICAgICAgcm90YXRlLFxuICAgICAgc3RyZWFtID0ge3BvaW50OiBwb2ludH07XG5cbiAgZnVuY3Rpb24gcG9pbnQoeCwgeSkge1xuICAgIHJpbmcucHVzaCh4ID0gcm90YXRlKHgsIHkpKTtcbiAgICB4WzBdICo9IGRlZ3JlZXMsIHhbMV0gKj0gZGVncmVlcztcbiAgfVxuXG4gIGZ1bmN0aW9uIGNpcmNsZSgpIHtcbiAgICB2YXIgYyA9IGNlbnRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpLFxuICAgICAgICByID0gcmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgKiByYWRpYW5zLFxuICAgICAgICBwID0gcHJlY2lzaW9uLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgKiByYWRpYW5zO1xuICAgIHJpbmcgPSBbXTtcbiAgICByb3RhdGUgPSByb3RhdGVSYWRpYW5zKC1jWzBdICogcmFkaWFucywgLWNbMV0gKiByYWRpYW5zLCAwKS5pbnZlcnQ7XG4gICAgY2lyY2xlU3RyZWFtKHN0cmVhbSwgciwgcCwgMSk7XG4gICAgYyA9IHt0eXBlOiBcIlBvbHlnb25cIiwgY29vcmRpbmF0ZXM6IFtyaW5nXX07XG4gICAgcmluZyA9IHJvdGF0ZSA9IG51bGw7XG4gICAgcmV0dXJuIGM7XG4gIH1cblxuICBjaXJjbGUuY2VudGVyID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNlbnRlciA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoWytfWzBdLCArX1sxXV0pLCBjaXJjbGUpIDogY2VudGVyO1xuICB9O1xuXG4gIGNpcmNsZS5yYWRpdXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFkaXVzID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGNpcmNsZSkgOiByYWRpdXM7XG4gIH07XG5cbiAgY2lyY2xlLnByZWNpc2lvbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwcmVjaXNpb24gPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgY2lyY2xlKSA6IHByZWNpc2lvbjtcbiAgfTtcblxuICByZXR1cm4gY2lyY2xlO1xufTtcblxudmFyIGNsaXBCdWZmZXIgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGxpbmVzID0gW10sXG4gICAgICBsaW5lO1xuICByZXR1cm4ge1xuICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICBsaW5lLnB1c2goW3gsIHldKTtcbiAgICB9LFxuICAgIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICBsaW5lcy5wdXNoKGxpbmUgPSBbXSk7XG4gICAgfSxcbiAgICBsaW5lRW5kOiBub29wLFxuICAgIHJlam9pbjogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAobGluZXMubGVuZ3RoID4gMSkgbGluZXMucHVzaChsaW5lcy5wb3AoKS5jb25jYXQobGluZXMuc2hpZnQoKSkpO1xuICAgIH0sXG4gICAgcmVzdWx0OiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciByZXN1bHQgPSBsaW5lcztcbiAgICAgIGxpbmVzID0gW107XG4gICAgICBsaW5lID0gbnVsbDtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9O1xufTtcblxudmFyIHBvaW50RXF1YWwgPSBmdW5jdGlvbihhLCBiKSB7XG4gIHJldHVybiBhYnMoYVswXSAtIGJbMF0pIDwgZXBzaWxvbiAmJiBhYnMoYVsxXSAtIGJbMV0pIDwgZXBzaWxvbjtcbn07XG5cbmZ1bmN0aW9uIEludGVyc2VjdGlvbihwb2ludCwgcG9pbnRzLCBvdGhlciwgZW50cnkpIHtcbiAgdGhpcy54ID0gcG9pbnQ7XG4gIHRoaXMueiA9IHBvaW50cztcbiAgdGhpcy5vID0gb3RoZXI7IC8vIGFub3RoZXIgaW50ZXJzZWN0aW9uXG4gIHRoaXMuZSA9IGVudHJ5OyAvLyBpcyBhbiBlbnRyeT9cbiAgdGhpcy52ID0gZmFsc2U7IC8vIHZpc2l0ZWRcbiAgdGhpcy5uID0gdGhpcy5wID0gbnVsbDsgLy8gbmV4dCAmIHByZXZpb3VzXG59XG5cbi8vIEEgZ2VuZXJhbGl6ZWQgcG9seWdvbiBjbGlwcGluZyBhbGdvcml0aG06IGdpdmVuIGEgcG9seWdvbiB0aGF0IGhhcyBiZWVuIGN1dFxuLy8gaW50byBpdHMgdmlzaWJsZSBsaW5lIHNlZ21lbnRzLCBhbmQgcmVqb2lucyB0aGUgc2VnbWVudHMgYnkgaW50ZXJwb2xhdGluZ1xuLy8gYWxvbmcgdGhlIGNsaXAgZWRnZS5cbnZhciBjbGlwUmVqb2luID0gZnVuY3Rpb24oc2VnbWVudHMsIGNvbXBhcmVJbnRlcnNlY3Rpb24sIHN0YXJ0SW5zaWRlLCBpbnRlcnBvbGF0ZSwgc3RyZWFtKSB7XG4gIHZhciBzdWJqZWN0ID0gW10sXG4gICAgICBjbGlwID0gW10sXG4gICAgICBpLFxuICAgICAgbjtcblxuICBzZWdtZW50cy5mb3JFYWNoKGZ1bmN0aW9uKHNlZ21lbnQpIHtcbiAgICBpZiAoKG4gPSBzZWdtZW50Lmxlbmd0aCAtIDEpIDw9IDApIHJldHVybjtcbiAgICB2YXIgbiwgcDAgPSBzZWdtZW50WzBdLCBwMSA9IHNlZ21lbnRbbl0sIHg7XG5cbiAgICAvLyBJZiB0aGUgZmlyc3QgYW5kIGxhc3QgcG9pbnRzIG9mIGEgc2VnbWVudCBhcmUgY29pbmNpZGVudCwgdGhlbiB0cmVhdCBhcyBhXG4gICAgLy8gY2xvc2VkIHJpbmcuIFRPRE8gaWYgYWxsIHJpbmdzIGFyZSBjbG9zZWQsIHRoZW4gdGhlIHdpbmRpbmcgb3JkZXIgb2YgdGhlXG4gICAgLy8gZXh0ZXJpb3IgcmluZyBzaG91bGQgYmUgY2hlY2tlZC5cbiAgICBpZiAocG9pbnRFcXVhbChwMCwgcDEpKSB7XG4gICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSBzdHJlYW0ucG9pbnQoKHAwID0gc2VnbWVudFtpXSlbMF0sIHAwWzFdKTtcbiAgICAgIHN0cmVhbS5saW5lRW5kKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc3ViamVjdC5wdXNoKHggPSBuZXcgSW50ZXJzZWN0aW9uKHAwLCBzZWdtZW50LCBudWxsLCB0cnVlKSk7XG4gICAgY2xpcC5wdXNoKHgubyA9IG5ldyBJbnRlcnNlY3Rpb24ocDAsIG51bGwsIHgsIGZhbHNlKSk7XG4gICAgc3ViamVjdC5wdXNoKHggPSBuZXcgSW50ZXJzZWN0aW9uKHAxLCBzZWdtZW50LCBudWxsLCBmYWxzZSkpO1xuICAgIGNsaXAucHVzaCh4Lm8gPSBuZXcgSW50ZXJzZWN0aW9uKHAxLCBudWxsLCB4LCB0cnVlKSk7XG4gIH0pO1xuXG4gIGlmICghc3ViamVjdC5sZW5ndGgpIHJldHVybjtcblxuICBjbGlwLnNvcnQoY29tcGFyZUludGVyc2VjdGlvbik7XG4gIGxpbmsoc3ViamVjdCk7XG4gIGxpbmsoY2xpcCk7XG5cbiAgZm9yIChpID0gMCwgbiA9IGNsaXAubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgY2xpcFtpXS5lID0gc3RhcnRJbnNpZGUgPSAhc3RhcnRJbnNpZGU7XG4gIH1cblxuICB2YXIgc3RhcnQgPSBzdWJqZWN0WzBdLFxuICAgICAgcG9pbnRzLFxuICAgICAgcG9pbnQ7XG5cbiAgd2hpbGUgKDEpIHtcbiAgICAvLyBGaW5kIGZpcnN0IHVudmlzaXRlZCBpbnRlcnNlY3Rpb24uXG4gICAgdmFyIGN1cnJlbnQgPSBzdGFydCxcbiAgICAgICAgaXNTdWJqZWN0ID0gdHJ1ZTtcbiAgICB3aGlsZSAoY3VycmVudC52KSBpZiAoKGN1cnJlbnQgPSBjdXJyZW50Lm4pID09PSBzdGFydCkgcmV0dXJuO1xuICAgIHBvaW50cyA9IGN1cnJlbnQuejtcbiAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgZG8ge1xuICAgICAgY3VycmVudC52ID0gY3VycmVudC5vLnYgPSB0cnVlO1xuICAgICAgaWYgKGN1cnJlbnQuZSkge1xuICAgICAgICBpZiAoaXNTdWJqZWN0KSB7XG4gICAgICAgICAgZm9yIChpID0gMCwgbiA9IHBvaW50cy5sZW5ndGg7IGkgPCBuOyArK2kpIHN0cmVhbS5wb2ludCgocG9pbnQgPSBwb2ludHNbaV0pWzBdLCBwb2ludFsxXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaW50ZXJwb2xhdGUoY3VycmVudC54LCBjdXJyZW50Lm4ueCwgMSwgc3RyZWFtKTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50ID0gY3VycmVudC5uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGlzU3ViamVjdCkge1xuICAgICAgICAgIHBvaW50cyA9IGN1cnJlbnQucC56O1xuICAgICAgICAgIGZvciAoaSA9IHBvaW50cy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgc3RyZWFtLnBvaW50KChwb2ludCA9IHBvaW50c1tpXSlbMF0sIHBvaW50WzFdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpbnRlcnBvbGF0ZShjdXJyZW50LngsIGN1cnJlbnQucC54LCAtMSwgc3RyZWFtKTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50ID0gY3VycmVudC5wO1xuICAgICAgfVxuICAgICAgY3VycmVudCA9IGN1cnJlbnQubztcbiAgICAgIHBvaW50cyA9IGN1cnJlbnQuejtcbiAgICAgIGlzU3ViamVjdCA9ICFpc1N1YmplY3Q7XG4gICAgfSB3aGlsZSAoIWN1cnJlbnQudik7XG4gICAgc3RyZWFtLmxpbmVFbmQoKTtcbiAgfVxufTtcblxuZnVuY3Rpb24gbGluayhhcnJheSkge1xuICBpZiAoIShuID0gYXJyYXkubGVuZ3RoKSkgcmV0dXJuO1xuICB2YXIgbixcbiAgICAgIGkgPSAwLFxuICAgICAgYSA9IGFycmF5WzBdLFxuICAgICAgYjtcbiAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICBhLm4gPSBiID0gYXJyYXlbaV07XG4gICAgYi5wID0gYTtcbiAgICBhID0gYjtcbiAgfVxuICBhLm4gPSBiID0gYXJyYXlbMF07XG4gIGIucCA9IGE7XG59XG5cbnZhciBzdW0gPSBhZGRlcigpO1xuXG52YXIgcG9seWdvbkNvbnRhaW5zID0gZnVuY3Rpb24ocG9seWdvbiwgcG9pbnQpIHtcbiAgdmFyIGxhbWJkYSA9IHBvaW50WzBdLFxuICAgICAgcGhpID0gcG9pbnRbMV0sXG4gICAgICBub3JtYWwgPSBbc2luKGxhbWJkYSksIC1jb3MobGFtYmRhKSwgMF0sXG4gICAgICBhbmdsZSA9IDAsXG4gICAgICB3aW5kaW5nID0gMDtcblxuICBzdW0ucmVzZXQoKTtcblxuICBmb3IgKHZhciBpID0gMCwgbiA9IHBvbHlnb24ubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgaWYgKCEobSA9IChyaW5nID0gcG9seWdvbltpXSkubGVuZ3RoKSkgY29udGludWU7XG4gICAgdmFyIHJpbmcsXG4gICAgICAgIG0sXG4gICAgICAgIHBvaW50MCA9IHJpbmdbbSAtIDFdLFxuICAgICAgICBsYW1iZGEwID0gcG9pbnQwWzBdLFxuICAgICAgICBwaGkwID0gcG9pbnQwWzFdIC8gMiArIHF1YXJ0ZXJQaSxcbiAgICAgICAgc2luUGhpMCA9IHNpbihwaGkwKSxcbiAgICAgICAgY29zUGhpMCA9IGNvcyhwaGkwKTtcblxuICAgIGZvciAodmFyIGogPSAwOyBqIDwgbTsgKytqLCBsYW1iZGEwID0gbGFtYmRhMSwgc2luUGhpMCA9IHNpblBoaTEsIGNvc1BoaTAgPSBjb3NQaGkxLCBwb2ludDAgPSBwb2ludDEpIHtcbiAgICAgIHZhciBwb2ludDEgPSByaW5nW2pdLFxuICAgICAgICAgIGxhbWJkYTEgPSBwb2ludDFbMF0sXG4gICAgICAgICAgcGhpMSA9IHBvaW50MVsxXSAvIDIgKyBxdWFydGVyUGksXG4gICAgICAgICAgc2luUGhpMSA9IHNpbihwaGkxKSxcbiAgICAgICAgICBjb3NQaGkxID0gY29zKHBoaTEpLFxuICAgICAgICAgIGRlbHRhID0gbGFtYmRhMSAtIGxhbWJkYTAsXG4gICAgICAgICAgc2lnbiQkMSA9IGRlbHRhID49IDAgPyAxIDogLTEsXG4gICAgICAgICAgYWJzRGVsdGEgPSBzaWduJCQxICogZGVsdGEsXG4gICAgICAgICAgYW50aW1lcmlkaWFuID0gYWJzRGVsdGEgPiBwaSxcbiAgICAgICAgICBrID0gc2luUGhpMCAqIHNpblBoaTE7XG5cbiAgICAgIHN1bS5hZGQoYXRhbjIoayAqIHNpZ24kJDEgKiBzaW4oYWJzRGVsdGEpLCBjb3NQaGkwICogY29zUGhpMSArIGsgKiBjb3MoYWJzRGVsdGEpKSk7XG4gICAgICBhbmdsZSArPSBhbnRpbWVyaWRpYW4gPyBkZWx0YSArIHNpZ24kJDEgKiB0YXUgOiBkZWx0YTtcblxuICAgICAgLy8gQXJlIHRoZSBsb25naXR1ZGVzIGVpdGhlciBzaWRlIG9mIHRoZSBwb2ludOKAmXMgbWVyaWRpYW4gKGxhbWJkYSksXG4gICAgICAvLyBhbmQgYXJlIHRoZSBsYXRpdHVkZXMgc21hbGxlciB0aGFuIHRoZSBwYXJhbGxlbCAocGhpKT9cbiAgICAgIGlmIChhbnRpbWVyaWRpYW4gXiBsYW1iZGEwID49IGxhbWJkYSBeIGxhbWJkYTEgPj0gbGFtYmRhKSB7XG4gICAgICAgIHZhciBhcmMgPSBjYXJ0ZXNpYW5Dcm9zcyhjYXJ0ZXNpYW4ocG9pbnQwKSwgY2FydGVzaWFuKHBvaW50MSkpO1xuICAgICAgICBjYXJ0ZXNpYW5Ob3JtYWxpemVJblBsYWNlKGFyYyk7XG4gICAgICAgIHZhciBpbnRlcnNlY3Rpb24gPSBjYXJ0ZXNpYW5Dcm9zcyhub3JtYWwsIGFyYyk7XG4gICAgICAgIGNhcnRlc2lhbk5vcm1hbGl6ZUluUGxhY2UoaW50ZXJzZWN0aW9uKTtcbiAgICAgICAgdmFyIHBoaUFyYyA9IChhbnRpbWVyaWRpYW4gXiBkZWx0YSA+PSAwID8gLTEgOiAxKSAqIGFzaW4oaW50ZXJzZWN0aW9uWzJdKTtcbiAgICAgICAgaWYgKHBoaSA+IHBoaUFyYyB8fCBwaGkgPT09IHBoaUFyYyAmJiAoYXJjWzBdIHx8IGFyY1sxXSkpIHtcbiAgICAgICAgICB3aW5kaW5nICs9IGFudGltZXJpZGlhbiBeIGRlbHRhID49IDAgPyAxIDogLTE7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBGaXJzdCwgZGV0ZXJtaW5lIHdoZXRoZXIgdGhlIFNvdXRoIHBvbGUgaXMgaW5zaWRlIG9yIG91dHNpZGU6XG4gIC8vXG4gIC8vIEl0IGlzIGluc2lkZSBpZjpcbiAgLy8gKiB0aGUgcG9seWdvbiB3aW5kcyBhcm91bmQgaXQgaW4gYSBjbG9ja3dpc2UgZGlyZWN0aW9uLlxuICAvLyAqIHRoZSBwb2x5Z29uIGRvZXMgbm90IChjdW11bGF0aXZlbHkpIHdpbmQgYXJvdW5kIGl0LCBidXQgaGFzIGEgbmVnYXRpdmVcbiAgLy8gICAoY291bnRlci1jbG9ja3dpc2UpIGFyZWEuXG4gIC8vXG4gIC8vIFNlY29uZCwgY291bnQgdGhlIChzaWduZWQpIG51bWJlciBvZiB0aW1lcyBhIHNlZ21lbnQgY3Jvc3NlcyBhIGxhbWJkYVxuICAvLyBmcm9tIHRoZSBwb2ludCB0byB0aGUgU291dGggcG9sZS4gIElmIGl0IGlzIHplcm8sIHRoZW4gdGhlIHBvaW50IGlzIHRoZVxuICAvLyBzYW1lIHNpZGUgYXMgdGhlIFNvdXRoIHBvbGUuXG5cbiAgcmV0dXJuIChhbmdsZSA8IC1lcHNpbG9uIHx8IGFuZ2xlIDwgZXBzaWxvbiAmJiBzdW0gPCAtZXBzaWxvbikgXiAod2luZGluZyAmIDEpO1xufTtcblxudmFyIGNsaXAgPSBmdW5jdGlvbihwb2ludFZpc2libGUsIGNsaXBMaW5lLCBpbnRlcnBvbGF0ZSwgc3RhcnQpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHNpbmspIHtcbiAgICB2YXIgbGluZSA9IGNsaXBMaW5lKHNpbmspLFxuICAgICAgICByaW5nQnVmZmVyID0gY2xpcEJ1ZmZlcigpLFxuICAgICAgICByaW5nU2luayA9IGNsaXBMaW5lKHJpbmdCdWZmZXIpLFxuICAgICAgICBwb2x5Z29uU3RhcnRlZCA9IGZhbHNlLFxuICAgICAgICBwb2x5Z29uLFxuICAgICAgICBzZWdtZW50cyxcbiAgICAgICAgcmluZztcblxuICAgIHZhciBjbGlwID0ge1xuICAgICAgcG9pbnQ6IHBvaW50LFxuICAgICAgbGluZVN0YXJ0OiBsaW5lU3RhcnQsXG4gICAgICBsaW5lRW5kOiBsaW5lRW5kLFxuICAgICAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50UmluZztcbiAgICAgICAgY2xpcC5saW5lU3RhcnQgPSByaW5nU3RhcnQ7XG4gICAgICAgIGNsaXAubGluZUVuZCA9IHJpbmdFbmQ7XG4gICAgICAgIHNlZ21lbnRzID0gW107XG4gICAgICAgIHBvbHlnb24gPSBbXTtcbiAgICAgIH0sXG4gICAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgY2xpcC5wb2ludCA9IHBvaW50O1xuICAgICAgICBjbGlwLmxpbmVTdGFydCA9IGxpbmVTdGFydDtcbiAgICAgICAgY2xpcC5saW5lRW5kID0gbGluZUVuZDtcbiAgICAgICAgc2VnbWVudHMgPSBkM0FycmF5Lm1lcmdlKHNlZ21lbnRzKTtcbiAgICAgICAgdmFyIHN0YXJ0SW5zaWRlID0gcG9seWdvbkNvbnRhaW5zKHBvbHlnb24sIHN0YXJ0KTtcbiAgICAgICAgaWYgKHNlZ21lbnRzLmxlbmd0aCkge1xuICAgICAgICAgIGlmICghcG9seWdvblN0YXJ0ZWQpIHNpbmsucG9seWdvblN0YXJ0KCksIHBvbHlnb25TdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgICBjbGlwUmVqb2luKHNlZ21lbnRzLCBjb21wYXJlSW50ZXJzZWN0aW9uLCBzdGFydEluc2lkZSwgaW50ZXJwb2xhdGUsIHNpbmspO1xuICAgICAgICB9IGVsc2UgaWYgKHN0YXJ0SW5zaWRlKSB7XG4gICAgICAgICAgaWYgKCFwb2x5Z29uU3RhcnRlZCkgc2luay5wb2x5Z29uU3RhcnQoKSwgcG9seWdvblN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgICAgIHNpbmsubGluZVN0YXJ0KCk7XG4gICAgICAgICAgaW50ZXJwb2xhdGUobnVsbCwgbnVsbCwgMSwgc2luayk7XG4gICAgICAgICAgc2luay5saW5lRW5kKCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBvbHlnb25TdGFydGVkKSBzaW5rLnBvbHlnb25FbmQoKSwgcG9seWdvblN0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgICAgc2VnbWVudHMgPSBwb2x5Z29uID0gbnVsbDtcbiAgICAgIH0sXG4gICAgICBzcGhlcmU6IGZ1bmN0aW9uKCkge1xuICAgICAgICBzaW5rLnBvbHlnb25TdGFydCgpO1xuICAgICAgICBzaW5rLmxpbmVTdGFydCgpO1xuICAgICAgICBpbnRlcnBvbGF0ZShudWxsLCBudWxsLCAxLCBzaW5rKTtcbiAgICAgICAgc2luay5saW5lRW5kKCk7XG4gICAgICAgIHNpbmsucG9seWdvbkVuZCgpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwb2ludChsYW1iZGEsIHBoaSkge1xuICAgICAgaWYgKHBvaW50VmlzaWJsZShsYW1iZGEsIHBoaSkpIHNpbmsucG9pbnQobGFtYmRhLCBwaGkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvaW50TGluZShsYW1iZGEsIHBoaSkge1xuICAgICAgbGluZS5wb2ludChsYW1iZGEsIHBoaSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGluZVN0YXJ0KCkge1xuICAgICAgY2xpcC5wb2ludCA9IHBvaW50TGluZTtcbiAgICAgIGxpbmUubGluZVN0YXJ0KCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgIGNsaXAucG9pbnQgPSBwb2ludDtcbiAgICAgIGxpbmUubGluZUVuZCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvaW50UmluZyhsYW1iZGEsIHBoaSkge1xuICAgICAgcmluZy5wdXNoKFtsYW1iZGEsIHBoaV0pO1xuICAgICAgcmluZ1NpbmsucG9pbnQobGFtYmRhLCBwaGkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJpbmdTdGFydCgpIHtcbiAgICAgIHJpbmdTaW5rLmxpbmVTdGFydCgpO1xuICAgICAgcmluZyA9IFtdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJpbmdFbmQoKSB7XG4gICAgICBwb2ludFJpbmcocmluZ1swXVswXSwgcmluZ1swXVsxXSk7XG4gICAgICByaW5nU2luay5saW5lRW5kKCk7XG5cbiAgICAgIHZhciBjbGVhbiA9IHJpbmdTaW5rLmNsZWFuKCksXG4gICAgICAgICAgcmluZ1NlZ21lbnRzID0gcmluZ0J1ZmZlci5yZXN1bHQoKSxcbiAgICAgICAgICBpLCBuID0gcmluZ1NlZ21lbnRzLmxlbmd0aCwgbSxcbiAgICAgICAgICBzZWdtZW50LFxuICAgICAgICAgIHBvaW50O1xuXG4gICAgICByaW5nLnBvcCgpO1xuICAgICAgcG9seWdvbi5wdXNoKHJpbmcpO1xuICAgICAgcmluZyA9IG51bGw7XG5cbiAgICAgIGlmICghbikgcmV0dXJuO1xuXG4gICAgICAvLyBObyBpbnRlcnNlY3Rpb25zLlxuICAgICAgaWYgKGNsZWFuICYgMSkge1xuICAgICAgICBzZWdtZW50ID0gcmluZ1NlZ21lbnRzWzBdO1xuICAgICAgICBpZiAoKG0gPSBzZWdtZW50Lmxlbmd0aCAtIDEpID4gMCkge1xuICAgICAgICAgIGlmICghcG9seWdvblN0YXJ0ZWQpIHNpbmsucG9seWdvblN0YXJ0KCksIHBvbHlnb25TdGFydGVkID0gdHJ1ZTtcbiAgICAgICAgICBzaW5rLmxpbmVTdGFydCgpO1xuICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBtOyArK2kpIHNpbmsucG9pbnQoKHBvaW50ID0gc2VnbWVudFtpXSlbMF0sIHBvaW50WzFdKTtcbiAgICAgICAgICBzaW5rLmxpbmVFbmQoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIFJlam9pbiBjb25uZWN0ZWQgc2VnbWVudHMuXG4gICAgICAvLyBUT0RPIHJldXNlIHJpbmdCdWZmZXIucmVqb2luKCk/XG4gICAgICBpZiAobiA+IDEgJiYgY2xlYW4gJiAyKSByaW5nU2VnbWVudHMucHVzaChyaW5nU2VnbWVudHMucG9wKCkuY29uY2F0KHJpbmdTZWdtZW50cy5zaGlmdCgpKSk7XG5cbiAgICAgIHNlZ21lbnRzLnB1c2gocmluZ1NlZ21lbnRzLmZpbHRlcih2YWxpZFNlZ21lbnQpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xpcDtcbiAgfTtcbn07XG5cbmZ1bmN0aW9uIHZhbGlkU2VnbWVudChzZWdtZW50KSB7XG4gIHJldHVybiBzZWdtZW50Lmxlbmd0aCA+IDE7XG59XG5cbi8vIEludGVyc2VjdGlvbnMgYXJlIHNvcnRlZCBhbG9uZyB0aGUgY2xpcCBlZGdlLiBGb3IgYm90aCBhbnRpbWVyaWRpYW4gY3V0dGluZ1xuLy8gYW5kIGNpcmNsZSBjbGlwcGluZywgdGhlIHNhbWUgY29tcGFyaXNvbiBpcyB1c2VkLlxuZnVuY3Rpb24gY29tcGFyZUludGVyc2VjdGlvbihhLCBiKSB7XG4gIHJldHVybiAoKGEgPSBhLngpWzBdIDwgMCA/IGFbMV0gLSBoYWxmUGkgLSBlcHNpbG9uIDogaGFsZlBpIC0gYVsxXSlcbiAgICAgICAtICgoYiA9IGIueClbMF0gPCAwID8gYlsxXSAtIGhhbGZQaSAtIGVwc2lsb24gOiBoYWxmUGkgLSBiWzFdKTtcbn1cblxudmFyIGNsaXBBbnRpbWVyaWRpYW4gPSBjbGlwKFxuICBmdW5jdGlvbigpIHsgcmV0dXJuIHRydWU7IH0sXG4gIGNsaXBBbnRpbWVyaWRpYW5MaW5lLFxuICBjbGlwQW50aW1lcmlkaWFuSW50ZXJwb2xhdGUsXG4gIFstcGksIC1oYWxmUGldXG4pO1xuXG4vLyBUYWtlcyBhIGxpbmUgYW5kIGN1dHMgaW50byB2aXNpYmxlIHNlZ21lbnRzLiBSZXR1cm4gdmFsdWVzOiAwIC0gdGhlcmUgd2VyZVxuLy8gaW50ZXJzZWN0aW9ucyBvciB0aGUgbGluZSB3YXMgZW1wdHk7IDEgLSBubyBpbnRlcnNlY3Rpb25zOyAyIC0gdGhlcmUgd2VyZVxuLy8gaW50ZXJzZWN0aW9ucywgYW5kIHRoZSBmaXJzdCBhbmQgbGFzdCBzZWdtZW50cyBzaG91bGQgYmUgcmVqb2luZWQuXG5mdW5jdGlvbiBjbGlwQW50aW1lcmlkaWFuTGluZShzdHJlYW0pIHtcbiAgdmFyIGxhbWJkYTAgPSBOYU4sXG4gICAgICBwaGkwID0gTmFOLFxuICAgICAgc2lnbjAgPSBOYU4sXG4gICAgICBjbGVhbjsgLy8gbm8gaW50ZXJzZWN0aW9uc1xuXG4gIHJldHVybiB7XG4gICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgIHN0cmVhbS5saW5lU3RhcnQoKTtcbiAgICAgIGNsZWFuID0gMTtcbiAgICB9LFxuICAgIHBvaW50OiBmdW5jdGlvbihsYW1iZGExLCBwaGkxKSB7XG4gICAgICB2YXIgc2lnbjEgPSBsYW1iZGExID4gMCA/IHBpIDogLXBpLFxuICAgICAgICAgIGRlbHRhID0gYWJzKGxhbWJkYTEgLSBsYW1iZGEwKTtcbiAgICAgIGlmIChhYnMoZGVsdGEgLSBwaSkgPCBlcHNpbG9uKSB7IC8vIGxpbmUgY3Jvc3NlcyBhIHBvbGVcbiAgICAgICAgc3RyZWFtLnBvaW50KGxhbWJkYTAsIHBoaTAgPSAocGhpMCArIHBoaTEpIC8gMiA+IDAgPyBoYWxmUGkgOiAtaGFsZlBpKTtcbiAgICAgICAgc3RyZWFtLnBvaW50KHNpZ24wLCBwaGkwKTtcbiAgICAgICAgc3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgICAgc3RyZWFtLmxpbmVTdGFydCgpO1xuICAgICAgICBzdHJlYW0ucG9pbnQoc2lnbjEsIHBoaTApO1xuICAgICAgICBzdHJlYW0ucG9pbnQobGFtYmRhMSwgcGhpMCk7XG4gICAgICAgIGNsZWFuID0gMDtcbiAgICAgIH0gZWxzZSBpZiAoc2lnbjAgIT09IHNpZ24xICYmIGRlbHRhID49IHBpKSB7IC8vIGxpbmUgY3Jvc3NlcyBhbnRpbWVyaWRpYW5cbiAgICAgICAgaWYgKGFicyhsYW1iZGEwIC0gc2lnbjApIDwgZXBzaWxvbikgbGFtYmRhMCAtPSBzaWduMCAqIGVwc2lsb247IC8vIGhhbmRsZSBkZWdlbmVyYWNpZXNcbiAgICAgICAgaWYgKGFicyhsYW1iZGExIC0gc2lnbjEpIDwgZXBzaWxvbikgbGFtYmRhMSAtPSBzaWduMSAqIGVwc2lsb247XG4gICAgICAgIHBoaTAgPSBjbGlwQW50aW1lcmlkaWFuSW50ZXJzZWN0KGxhbWJkYTAsIHBoaTAsIGxhbWJkYTEsIHBoaTEpO1xuICAgICAgICBzdHJlYW0ucG9pbnQoc2lnbjAsIHBoaTApO1xuICAgICAgICBzdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgIHN0cmVhbS5wb2ludChzaWduMSwgcGhpMCk7XG4gICAgICAgIGNsZWFuID0gMDtcbiAgICAgIH1cbiAgICAgIHN0cmVhbS5wb2ludChsYW1iZGEwID0gbGFtYmRhMSwgcGhpMCA9IHBoaTEpO1xuICAgICAgc2lnbjAgPSBzaWduMTtcbiAgICB9LFxuICAgIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgc3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgIGxhbWJkYTAgPSBwaGkwID0gTmFOO1xuICAgIH0sXG4gICAgY2xlYW46IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIDIgLSBjbGVhbjsgLy8gaWYgaW50ZXJzZWN0aW9ucywgcmVqb2luIGZpcnN0IGFuZCBsYXN0IHNlZ21lbnRzXG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBjbGlwQW50aW1lcmlkaWFuSW50ZXJzZWN0KGxhbWJkYTAsIHBoaTAsIGxhbWJkYTEsIHBoaTEpIHtcbiAgdmFyIGNvc1BoaTAsXG4gICAgICBjb3NQaGkxLFxuICAgICAgc2luTGFtYmRhMExhbWJkYTEgPSBzaW4obGFtYmRhMCAtIGxhbWJkYTEpO1xuICByZXR1cm4gYWJzKHNpbkxhbWJkYTBMYW1iZGExKSA+IGVwc2lsb25cbiAgICAgID8gYXRhbigoc2luKHBoaTApICogKGNvc1BoaTEgPSBjb3MocGhpMSkpICogc2luKGxhbWJkYTEpXG4gICAgICAgICAgLSBzaW4ocGhpMSkgKiAoY29zUGhpMCA9IGNvcyhwaGkwKSkgKiBzaW4obGFtYmRhMCkpXG4gICAgICAgICAgLyAoY29zUGhpMCAqIGNvc1BoaTEgKiBzaW5MYW1iZGEwTGFtYmRhMSkpXG4gICAgICA6IChwaGkwICsgcGhpMSkgLyAyO1xufVxuXG5mdW5jdGlvbiBjbGlwQW50aW1lcmlkaWFuSW50ZXJwb2xhdGUoZnJvbSwgdG8sIGRpcmVjdGlvbiwgc3RyZWFtKSB7XG4gIHZhciBwaGk7XG4gIGlmIChmcm9tID09IG51bGwpIHtcbiAgICBwaGkgPSBkaXJlY3Rpb24gKiBoYWxmUGk7XG4gICAgc3RyZWFtLnBvaW50KC1waSwgcGhpKTtcbiAgICBzdHJlYW0ucG9pbnQoMCwgcGhpKTtcbiAgICBzdHJlYW0ucG9pbnQocGksIHBoaSk7XG4gICAgc3RyZWFtLnBvaW50KHBpLCAwKTtcbiAgICBzdHJlYW0ucG9pbnQocGksIC1waGkpO1xuICAgIHN0cmVhbS5wb2ludCgwLCAtcGhpKTtcbiAgICBzdHJlYW0ucG9pbnQoLXBpLCAtcGhpKTtcbiAgICBzdHJlYW0ucG9pbnQoLXBpLCAwKTtcbiAgICBzdHJlYW0ucG9pbnQoLXBpLCBwaGkpO1xuICB9IGVsc2UgaWYgKGFicyhmcm9tWzBdIC0gdG9bMF0pID4gZXBzaWxvbikge1xuICAgIHZhciBsYW1iZGEgPSBmcm9tWzBdIDwgdG9bMF0gPyBwaSA6IC1waTtcbiAgICBwaGkgPSBkaXJlY3Rpb24gKiBsYW1iZGEgLyAyO1xuICAgIHN0cmVhbS5wb2ludCgtbGFtYmRhLCBwaGkpO1xuICAgIHN0cmVhbS5wb2ludCgwLCBwaGkpO1xuICAgIHN0cmVhbS5wb2ludChsYW1iZGEsIHBoaSk7XG4gIH0gZWxzZSB7XG4gICAgc3RyZWFtLnBvaW50KHRvWzBdLCB0b1sxXSk7XG4gIH1cbn1cblxudmFyIGNsaXBDaXJjbGUgPSBmdW5jdGlvbihyYWRpdXMpIHtcbiAgdmFyIGNyID0gY29zKHJhZGl1cyksXG4gICAgICBkZWx0YSA9IDYgKiByYWRpYW5zLFxuICAgICAgc21hbGxSYWRpdXMgPSBjciA+IDAsXG4gICAgICBub3RIZW1pc3BoZXJlID0gYWJzKGNyKSA+IGVwc2lsb247IC8vIFRPRE8gb3B0aW1pc2UgZm9yIHRoaXMgY29tbW9uIGNhc2VcblxuICBmdW5jdGlvbiBpbnRlcnBvbGF0ZShmcm9tLCB0bywgZGlyZWN0aW9uLCBzdHJlYW0pIHtcbiAgICBjaXJjbGVTdHJlYW0oc3RyZWFtLCByYWRpdXMsIGRlbHRhLCBkaXJlY3Rpb24sIGZyb20sIHRvKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHZpc2libGUobGFtYmRhLCBwaGkpIHtcbiAgICByZXR1cm4gY29zKGxhbWJkYSkgKiBjb3MocGhpKSA+IGNyO1xuICB9XG5cbiAgLy8gVGFrZXMgYSBsaW5lIGFuZCBjdXRzIGludG8gdmlzaWJsZSBzZWdtZW50cy4gUmV0dXJuIHZhbHVlcyB1c2VkIGZvciBwb2x5Z29uXG4gIC8vIGNsaXBwaW5nOiAwIC0gdGhlcmUgd2VyZSBpbnRlcnNlY3Rpb25zIG9yIHRoZSBsaW5lIHdhcyBlbXB0eTsgMSAtIG5vXG4gIC8vIGludGVyc2VjdGlvbnMgMiAtIHRoZXJlIHdlcmUgaW50ZXJzZWN0aW9ucywgYW5kIHRoZSBmaXJzdCBhbmQgbGFzdCBzZWdtZW50c1xuICAvLyBzaG91bGQgYmUgcmVqb2luZWQuXG4gIGZ1bmN0aW9uIGNsaXBMaW5lKHN0cmVhbSkge1xuICAgIHZhciBwb2ludDAsIC8vIHByZXZpb3VzIHBvaW50XG4gICAgICAgIGMwLCAvLyBjb2RlIGZvciBwcmV2aW91cyBwb2ludFxuICAgICAgICB2MCwgLy8gdmlzaWJpbGl0eSBvZiBwcmV2aW91cyBwb2ludFxuICAgICAgICB2MDAsIC8vIHZpc2liaWxpdHkgb2YgZmlyc3QgcG9pbnRcbiAgICAgICAgY2xlYW47IC8vIG5vIGludGVyc2VjdGlvbnNcbiAgICByZXR1cm4ge1xuICAgICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgdjAwID0gdjAgPSBmYWxzZTtcbiAgICAgICAgY2xlYW4gPSAxO1xuICAgICAgfSxcbiAgICAgIHBvaW50OiBmdW5jdGlvbihsYW1iZGEsIHBoaSkge1xuICAgICAgICB2YXIgcG9pbnQxID0gW2xhbWJkYSwgcGhpXSxcbiAgICAgICAgICAgIHBvaW50MixcbiAgICAgICAgICAgIHYgPSB2aXNpYmxlKGxhbWJkYSwgcGhpKSxcbiAgICAgICAgICAgIGMgPSBzbWFsbFJhZGl1c1xuICAgICAgICAgICAgICA/IHYgPyAwIDogY29kZShsYW1iZGEsIHBoaSlcbiAgICAgICAgICAgICAgOiB2ID8gY29kZShsYW1iZGEgKyAobGFtYmRhIDwgMCA/IHBpIDogLXBpKSwgcGhpKSA6IDA7XG4gICAgICAgIGlmICghcG9pbnQwICYmICh2MDAgPSB2MCA9IHYpKSBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgIC8vIEhhbmRsZSBkZWdlbmVyYWNpZXMuXG4gICAgICAgIC8vIFRPRE8gaWdub3JlIGlmIG5vdCBjbGlwcGluZyBwb2x5Z29ucy5cbiAgICAgICAgaWYgKHYgIT09IHYwKSB7XG4gICAgICAgICAgcG9pbnQyID0gaW50ZXJzZWN0KHBvaW50MCwgcG9pbnQxKTtcbiAgICAgICAgICBpZiAoIXBvaW50MiB8fCBwb2ludEVxdWFsKHBvaW50MCwgcG9pbnQyKSB8fCBwb2ludEVxdWFsKHBvaW50MSwgcG9pbnQyKSkge1xuICAgICAgICAgICAgcG9pbnQxWzBdICs9IGVwc2lsb247XG4gICAgICAgICAgICBwb2ludDFbMV0gKz0gZXBzaWxvbjtcbiAgICAgICAgICAgIHYgPSB2aXNpYmxlKHBvaW50MVswXSwgcG9pbnQxWzFdKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHYgIT09IHYwKSB7XG4gICAgICAgICAgY2xlYW4gPSAwO1xuICAgICAgICAgIGlmICh2KSB7XG4gICAgICAgICAgICAvLyBvdXRzaWRlIGdvaW5nIGluXG4gICAgICAgICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICBwb2ludDIgPSBpbnRlcnNlY3QocG9pbnQxLCBwb2ludDApO1xuICAgICAgICAgICAgc3RyZWFtLnBvaW50KHBvaW50MlswXSwgcG9pbnQyWzFdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gaW5zaWRlIGdvaW5nIG91dFxuICAgICAgICAgICAgcG9pbnQyID0gaW50ZXJzZWN0KHBvaW50MCwgcG9pbnQxKTtcbiAgICAgICAgICAgIHN0cmVhbS5wb2ludChwb2ludDJbMF0sIHBvaW50MlsxXSk7XG4gICAgICAgICAgICBzdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwb2ludDAgPSBwb2ludDI7XG4gICAgICAgIH0gZWxzZSBpZiAobm90SGVtaXNwaGVyZSAmJiBwb2ludDAgJiYgc21hbGxSYWRpdXMgXiB2KSB7XG4gICAgICAgICAgdmFyIHQ7XG4gICAgICAgICAgLy8gSWYgdGhlIGNvZGVzIGZvciB0d28gcG9pbnRzIGFyZSBkaWZmZXJlbnQsIG9yIGFyZSBib3RoIHplcm8sXG4gICAgICAgICAgLy8gYW5kIHRoZXJlIHRoaXMgc2VnbWVudCBpbnRlcnNlY3RzIHdpdGggdGhlIHNtYWxsIGNpcmNsZS5cbiAgICAgICAgICBpZiAoIShjICYgYzApICYmICh0ID0gaW50ZXJzZWN0KHBvaW50MSwgcG9pbnQwLCB0cnVlKSkpIHtcbiAgICAgICAgICAgIGNsZWFuID0gMDtcbiAgICAgICAgICAgIGlmIChzbWFsbFJhZGl1cykge1xuICAgICAgICAgICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgIHN0cmVhbS5wb2ludCh0WzBdWzBdLCB0WzBdWzFdKTtcbiAgICAgICAgICAgICAgc3RyZWFtLnBvaW50KHRbMV1bMF0sIHRbMV1bMV0pO1xuICAgICAgICAgICAgICBzdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgc3RyZWFtLnBvaW50KHRbMV1bMF0sIHRbMV1bMV0pO1xuICAgICAgICAgICAgICBzdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICAgICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgIHN0cmVhbS5wb2ludCh0WzBdWzBdLCB0WzBdWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHYgJiYgKCFwb2ludDAgfHwgIXBvaW50RXF1YWwocG9pbnQwLCBwb2ludDEpKSkge1xuICAgICAgICAgIHN0cmVhbS5wb2ludChwb2ludDFbMF0sIHBvaW50MVsxXSk7XG4gICAgICAgIH1cbiAgICAgICAgcG9pbnQwID0gcG9pbnQxLCB2MCA9IHYsIGMwID0gYztcbiAgICAgIH0sXG4gICAgICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHYwKSBzdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICBwb2ludDAgPSBudWxsO1xuICAgICAgfSxcbiAgICAgIC8vIFJlam9pbiBmaXJzdCBhbmQgbGFzdCBzZWdtZW50cyBpZiB0aGVyZSB3ZXJlIGludGVyc2VjdGlvbnMgYW5kIHRoZSBmaXJzdFxuICAgICAgLy8gYW5kIGxhc3QgcG9pbnRzIHdlcmUgdmlzaWJsZS5cbiAgICAgIGNsZWFuOiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIGNsZWFuIHwgKCh2MDAgJiYgdjApIDw8IDEpO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICAvLyBJbnRlcnNlY3RzIHRoZSBncmVhdCBjaXJjbGUgYmV0d2VlbiBhIGFuZCBiIHdpdGggdGhlIGNsaXAgY2lyY2xlLlxuICBmdW5jdGlvbiBpbnRlcnNlY3QoYSwgYiwgdHdvKSB7XG4gICAgdmFyIHBhID0gY2FydGVzaWFuKGEpLFxuICAgICAgICBwYiA9IGNhcnRlc2lhbihiKTtcblxuICAgIC8vIFdlIGhhdmUgdHdvIHBsYW5lcywgbjEucCA9IGQxIGFuZCBuMi5wID0gZDIuXG4gICAgLy8gRmluZCBpbnRlcnNlY3Rpb24gbGluZSBwKHQpID0gYzEgbjEgKyBjMiBuMiArIHQgKG4xIOKoryBuMikuXG4gICAgdmFyIG4xID0gWzEsIDAsIDBdLCAvLyBub3JtYWxcbiAgICAgICAgbjIgPSBjYXJ0ZXNpYW5Dcm9zcyhwYSwgcGIpLFxuICAgICAgICBuMm4yID0gY2FydGVzaWFuRG90KG4yLCBuMiksXG4gICAgICAgIG4xbjIgPSBuMlswXSwgLy8gY2FydGVzaWFuRG90KG4xLCBuMiksXG4gICAgICAgIGRldGVybWluYW50ID0gbjJuMiAtIG4xbjIgKiBuMW4yO1xuXG4gICAgLy8gVHdvIHBvbGFyIHBvaW50cy5cbiAgICBpZiAoIWRldGVybWluYW50KSByZXR1cm4gIXR3byAmJiBhO1xuXG4gICAgdmFyIGMxID0gIGNyICogbjJuMiAvIGRldGVybWluYW50LFxuICAgICAgICBjMiA9IC1jciAqIG4xbjIgLyBkZXRlcm1pbmFudCxcbiAgICAgICAgbjF4bjIgPSBjYXJ0ZXNpYW5Dcm9zcyhuMSwgbjIpLFxuICAgICAgICBBID0gY2FydGVzaWFuU2NhbGUobjEsIGMxKSxcbiAgICAgICAgQiA9IGNhcnRlc2lhblNjYWxlKG4yLCBjMik7XG4gICAgY2FydGVzaWFuQWRkSW5QbGFjZShBLCBCKTtcblxuICAgIC8vIFNvbHZlIHxwKHQpfF4yID0gMS5cbiAgICB2YXIgdSA9IG4xeG4yLFxuICAgICAgICB3ID0gY2FydGVzaWFuRG90KEEsIHUpLFxuICAgICAgICB1dSA9IGNhcnRlc2lhbkRvdCh1LCB1KSxcbiAgICAgICAgdDIgPSB3ICogdyAtIHV1ICogKGNhcnRlc2lhbkRvdChBLCBBKSAtIDEpO1xuXG4gICAgaWYgKHQyIDwgMCkgcmV0dXJuO1xuXG4gICAgdmFyIHQgPSBzcXJ0KHQyKSxcbiAgICAgICAgcSA9IGNhcnRlc2lhblNjYWxlKHUsICgtdyAtIHQpIC8gdXUpO1xuICAgIGNhcnRlc2lhbkFkZEluUGxhY2UocSwgQSk7XG4gICAgcSA9IHNwaGVyaWNhbChxKTtcblxuICAgIGlmICghdHdvKSByZXR1cm4gcTtcblxuICAgIC8vIFR3byBpbnRlcnNlY3Rpb24gcG9pbnRzLlxuICAgIHZhciBsYW1iZGEwID0gYVswXSxcbiAgICAgICAgbGFtYmRhMSA9IGJbMF0sXG4gICAgICAgIHBoaTAgPSBhWzFdLFxuICAgICAgICBwaGkxID0gYlsxXSxcbiAgICAgICAgejtcblxuICAgIGlmIChsYW1iZGExIDwgbGFtYmRhMCkgeiA9IGxhbWJkYTAsIGxhbWJkYTAgPSBsYW1iZGExLCBsYW1iZGExID0gejtcblxuICAgIHZhciBkZWx0YSA9IGxhbWJkYTEgLSBsYW1iZGEwLFxuICAgICAgICBwb2xhciA9IGFicyhkZWx0YSAtIHBpKSA8IGVwc2lsb24sXG4gICAgICAgIG1lcmlkaWFuID0gcG9sYXIgfHwgZGVsdGEgPCBlcHNpbG9uO1xuXG4gICAgaWYgKCFwb2xhciAmJiBwaGkxIDwgcGhpMCkgeiA9IHBoaTAsIHBoaTAgPSBwaGkxLCBwaGkxID0gejtcblxuICAgIC8vIENoZWNrIHRoYXQgdGhlIGZpcnN0IHBvaW50IGlzIGJldHdlZW4gYSBhbmQgYi5cbiAgICBpZiAobWVyaWRpYW5cbiAgICAgICAgPyBwb2xhclxuICAgICAgICAgID8gcGhpMCArIHBoaTEgPiAwIF4gcVsxXSA8IChhYnMocVswXSAtIGxhbWJkYTApIDwgZXBzaWxvbiA/IHBoaTAgOiBwaGkxKVxuICAgICAgICAgIDogcGhpMCA8PSBxWzFdICYmIHFbMV0gPD0gcGhpMVxuICAgICAgICA6IGRlbHRhID4gcGkgXiAobGFtYmRhMCA8PSBxWzBdICYmIHFbMF0gPD0gbGFtYmRhMSkpIHtcbiAgICAgIHZhciBxMSA9IGNhcnRlc2lhblNjYWxlKHUsICgtdyArIHQpIC8gdXUpO1xuICAgICAgY2FydGVzaWFuQWRkSW5QbGFjZShxMSwgQSk7XG4gICAgICByZXR1cm4gW3EsIHNwaGVyaWNhbChxMSldO1xuICAgIH1cbiAgfVxuXG4gIC8vIEdlbmVyYXRlcyBhIDQtYml0IHZlY3RvciByZXByZXNlbnRpbmcgdGhlIGxvY2F0aW9uIG9mIGEgcG9pbnQgcmVsYXRpdmUgdG9cbiAgLy8gdGhlIHNtYWxsIGNpcmNsZSdzIGJvdW5kaW5nIGJveC5cbiAgZnVuY3Rpb24gY29kZShsYW1iZGEsIHBoaSkge1xuICAgIHZhciByID0gc21hbGxSYWRpdXMgPyByYWRpdXMgOiBwaSAtIHJhZGl1cyxcbiAgICAgICAgY29kZSA9IDA7XG4gICAgaWYgKGxhbWJkYSA8IC1yKSBjb2RlIHw9IDE7IC8vIGxlZnRcbiAgICBlbHNlIGlmIChsYW1iZGEgPiByKSBjb2RlIHw9IDI7IC8vIHJpZ2h0XG4gICAgaWYgKHBoaSA8IC1yKSBjb2RlIHw9IDQ7IC8vIGJlbG93XG4gICAgZWxzZSBpZiAocGhpID4gcikgY29kZSB8PSA4OyAvLyBhYm92ZVxuICAgIHJldHVybiBjb2RlO1xuICB9XG5cbiAgcmV0dXJuIGNsaXAodmlzaWJsZSwgY2xpcExpbmUsIGludGVycG9sYXRlLCBzbWFsbFJhZGl1cyA/IFswLCAtcmFkaXVzXSA6IFstcGksIHJhZGl1cyAtIHBpXSk7XG59O1xuXG52YXIgY2xpcExpbmUgPSBmdW5jdGlvbihhLCBiLCB4MCwgeTAsIHgxLCB5MSkge1xuICB2YXIgYXggPSBhWzBdLFxuICAgICAgYXkgPSBhWzFdLFxuICAgICAgYnggPSBiWzBdLFxuICAgICAgYnkgPSBiWzFdLFxuICAgICAgdDAgPSAwLFxuICAgICAgdDEgPSAxLFxuICAgICAgZHggPSBieCAtIGF4LFxuICAgICAgZHkgPSBieSAtIGF5LFxuICAgICAgcjtcblxuICByID0geDAgLSBheDtcbiAgaWYgKCFkeCAmJiByID4gMCkgcmV0dXJuO1xuICByIC89IGR4O1xuICBpZiAoZHggPCAwKSB7XG4gICAgaWYgKHIgPCB0MCkgcmV0dXJuO1xuICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgfSBlbHNlIGlmIChkeCA+IDApIHtcbiAgICBpZiAociA+IHQxKSByZXR1cm47XG4gICAgaWYgKHIgPiB0MCkgdDAgPSByO1xuICB9XG5cbiAgciA9IHgxIC0gYXg7XG4gIGlmICghZHggJiYgciA8IDApIHJldHVybjtcbiAgciAvPSBkeDtcbiAgaWYgKGR4IDwgMCkge1xuICAgIGlmIChyID4gdDEpIHJldHVybjtcbiAgICBpZiAociA+IHQwKSB0MCA9IHI7XG4gIH0gZWxzZSBpZiAoZHggPiAwKSB7XG4gICAgaWYgKHIgPCB0MCkgcmV0dXJuO1xuICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgfVxuXG4gIHIgPSB5MCAtIGF5O1xuICBpZiAoIWR5ICYmIHIgPiAwKSByZXR1cm47XG4gIHIgLz0gZHk7XG4gIGlmIChkeSA8IDApIHtcbiAgICBpZiAociA8IHQwKSByZXR1cm47XG4gICAgaWYgKHIgPCB0MSkgdDEgPSByO1xuICB9IGVsc2UgaWYgKGR5ID4gMCkge1xuICAgIGlmIChyID4gdDEpIHJldHVybjtcbiAgICBpZiAociA+IHQwKSB0MCA9IHI7XG4gIH1cblxuICByID0geTEgLSBheTtcbiAgaWYgKCFkeSAmJiByIDwgMCkgcmV0dXJuO1xuICByIC89IGR5O1xuICBpZiAoZHkgPCAwKSB7XG4gICAgaWYgKHIgPiB0MSkgcmV0dXJuO1xuICAgIGlmIChyID4gdDApIHQwID0gcjtcbiAgfSBlbHNlIGlmIChkeSA+IDApIHtcbiAgICBpZiAociA8IHQwKSByZXR1cm47XG4gICAgaWYgKHIgPCB0MSkgdDEgPSByO1xuICB9XG5cbiAgaWYgKHQwID4gMCkgYVswXSA9IGF4ICsgdDAgKiBkeCwgYVsxXSA9IGF5ICsgdDAgKiBkeTtcbiAgaWYgKHQxIDwgMSkgYlswXSA9IGF4ICsgdDEgKiBkeCwgYlsxXSA9IGF5ICsgdDEgKiBkeTtcbiAgcmV0dXJuIHRydWU7XG59O1xuXG52YXIgY2xpcE1heCA9IDFlOTtcbnZhciBjbGlwTWluID0gLWNsaXBNYXg7XG5cbi8vIFRPRE8gVXNlIGQzLXBvbHlnb27igJlzIHBvbHlnb25Db250YWlucyBoZXJlIGZvciB0aGUgcmluZyBjaGVjaz9cbi8vIFRPRE8gRWxpbWluYXRlIGR1cGxpY2F0ZSBidWZmZXJpbmcgaW4gY2xpcEJ1ZmZlciBhbmQgcG9seWdvbi5wdXNoP1xuXG5mdW5jdGlvbiBjbGlwUmVjdGFuZ2xlKHgwLCB5MCwgeDEsIHkxKSB7XG5cbiAgZnVuY3Rpb24gdmlzaWJsZSh4LCB5KSB7XG4gICAgcmV0dXJuIHgwIDw9IHggJiYgeCA8PSB4MSAmJiB5MCA8PSB5ICYmIHkgPD0geTE7XG4gIH1cblxuICBmdW5jdGlvbiBpbnRlcnBvbGF0ZShmcm9tLCB0bywgZGlyZWN0aW9uLCBzdHJlYW0pIHtcbiAgICB2YXIgYSA9IDAsIGExID0gMDtcbiAgICBpZiAoZnJvbSA9PSBudWxsXG4gICAgICAgIHx8IChhID0gY29ybmVyKGZyb20sIGRpcmVjdGlvbikpICE9PSAoYTEgPSBjb3JuZXIodG8sIGRpcmVjdGlvbikpXG4gICAgICAgIHx8IGNvbXBhcmVQb2ludChmcm9tLCB0bykgPCAwIF4gZGlyZWN0aW9uID4gMCkge1xuICAgICAgZG8gc3RyZWFtLnBvaW50KGEgPT09IDAgfHwgYSA9PT0gMyA/IHgwIDogeDEsIGEgPiAxID8geTEgOiB5MCk7XG4gICAgICB3aGlsZSAoKGEgPSAoYSArIGRpcmVjdGlvbiArIDQpICUgNCkgIT09IGExKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyZWFtLnBvaW50KHRvWzBdLCB0b1sxXSk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY29ybmVyKHAsIGRpcmVjdGlvbikge1xuICAgIHJldHVybiBhYnMocFswXSAtIHgwKSA8IGVwc2lsb24gPyBkaXJlY3Rpb24gPiAwID8gMCA6IDNcbiAgICAgICAgOiBhYnMocFswXSAtIHgxKSA8IGVwc2lsb24gPyBkaXJlY3Rpb24gPiAwID8gMiA6IDFcbiAgICAgICAgOiBhYnMocFsxXSAtIHkwKSA8IGVwc2lsb24gPyBkaXJlY3Rpb24gPiAwID8gMSA6IDBcbiAgICAgICAgOiBkaXJlY3Rpb24gPiAwID8gMyA6IDI7IC8vIGFicyhwWzFdIC0geTEpIDwgZXBzaWxvblxuICB9XG5cbiAgZnVuY3Rpb24gY29tcGFyZUludGVyc2VjdGlvbihhLCBiKSB7XG4gICAgcmV0dXJuIGNvbXBhcmVQb2ludChhLngsIGIueCk7XG4gIH1cblxuICBmdW5jdGlvbiBjb21wYXJlUG9pbnQoYSwgYikge1xuICAgIHZhciBjYSA9IGNvcm5lcihhLCAxKSxcbiAgICAgICAgY2IgPSBjb3JuZXIoYiwgMSk7XG4gICAgcmV0dXJuIGNhICE9PSBjYiA/IGNhIC0gY2JcbiAgICAgICAgOiBjYSA9PT0gMCA/IGJbMV0gLSBhWzFdXG4gICAgICAgIDogY2EgPT09IDEgPyBhWzBdIC0gYlswXVxuICAgICAgICA6IGNhID09PSAyID8gYVsxXSAtIGJbMV1cbiAgICAgICAgOiBiWzBdIC0gYVswXTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICB2YXIgYWN0aXZlU3RyZWFtID0gc3RyZWFtLFxuICAgICAgICBidWZmZXJTdHJlYW0gPSBjbGlwQnVmZmVyKCksXG4gICAgICAgIHNlZ21lbnRzLFxuICAgICAgICBwb2x5Z29uLFxuICAgICAgICByaW5nLFxuICAgICAgICB4X18sIHlfXywgdl9fLCAvLyBmaXJzdCBwb2ludFxuICAgICAgICB4XywgeV8sIHZfLCAvLyBwcmV2aW91cyBwb2ludFxuICAgICAgICBmaXJzdCxcbiAgICAgICAgY2xlYW47XG5cbiAgICB2YXIgY2xpcFN0cmVhbSA9IHtcbiAgICAgIHBvaW50OiBwb2ludCxcbiAgICAgIGxpbmVTdGFydDogbGluZVN0YXJ0LFxuICAgICAgbGluZUVuZDogbGluZUVuZCxcbiAgICAgIHBvbHlnb25TdGFydDogcG9seWdvblN0YXJ0LFxuICAgICAgcG9seWdvbkVuZDogcG9seWdvbkVuZFxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwb2ludCh4LCB5KSB7XG4gICAgICBpZiAodmlzaWJsZSh4LCB5KSkgYWN0aXZlU3RyZWFtLnBvaW50KHgsIHkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBvbHlnb25JbnNpZGUoKSB7XG4gICAgICB2YXIgd2luZGluZyA9IDA7XG5cbiAgICAgIGZvciAodmFyIGkgPSAwLCBuID0gcG9seWdvbi5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgZm9yICh2YXIgcmluZyA9IHBvbHlnb25baV0sIGogPSAxLCBtID0gcmluZy5sZW5ndGgsIHBvaW50ID0gcmluZ1swXSwgYTAsIGExLCBiMCA9IHBvaW50WzBdLCBiMSA9IHBvaW50WzFdOyBqIDwgbTsgKytqKSB7XG4gICAgICAgICAgYTAgPSBiMCwgYTEgPSBiMSwgcG9pbnQgPSByaW5nW2pdLCBiMCA9IHBvaW50WzBdLCBiMSA9IHBvaW50WzFdO1xuICAgICAgICAgIGlmIChhMSA8PSB5MSkgeyBpZiAoYjEgPiB5MSAmJiAoYjAgLSBhMCkgKiAoeTEgLSBhMSkgPiAoYjEgLSBhMSkgKiAoeDAgLSBhMCkpICsrd2luZGluZzsgfVxuICAgICAgICAgIGVsc2UgeyBpZiAoYjEgPD0geTEgJiYgKGIwIC0gYTApICogKHkxIC0gYTEpIDwgKGIxIC0gYTEpICogKHgwIC0gYTApKSAtLXdpbmRpbmc7IH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gd2luZGluZztcbiAgICB9XG5cbiAgICAvLyBCdWZmZXIgZ2VvbWV0cnkgd2l0aGluIGEgcG9seWdvbiBhbmQgdGhlbiBjbGlwIGl0IGVuIG1hc3NlLlxuICAgIGZ1bmN0aW9uIHBvbHlnb25TdGFydCgpIHtcbiAgICAgIGFjdGl2ZVN0cmVhbSA9IGJ1ZmZlclN0cmVhbSwgc2VnbWVudHMgPSBbXSwgcG9seWdvbiA9IFtdLCBjbGVhbiA9IHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcG9seWdvbkVuZCgpIHtcbiAgICAgIHZhciBzdGFydEluc2lkZSA9IHBvbHlnb25JbnNpZGUoKSxcbiAgICAgICAgICBjbGVhbkluc2lkZSA9IGNsZWFuICYmIHN0YXJ0SW5zaWRlLFxuICAgICAgICAgIHZpc2libGUgPSAoc2VnbWVudHMgPSBkM0FycmF5Lm1lcmdlKHNlZ21lbnRzKSkubGVuZ3RoO1xuICAgICAgaWYgKGNsZWFuSW5zaWRlIHx8IHZpc2libGUpIHtcbiAgICAgICAgc3RyZWFtLnBvbHlnb25TdGFydCgpO1xuICAgICAgICBpZiAoY2xlYW5JbnNpZGUpIHtcbiAgICAgICAgICBzdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgICAgaW50ZXJwb2xhdGUobnVsbCwgbnVsbCwgMSwgc3RyZWFtKTtcbiAgICAgICAgICBzdHJlYW0ubGluZUVuZCgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2aXNpYmxlKSB7XG4gICAgICAgICAgY2xpcFJlam9pbihzZWdtZW50cywgY29tcGFyZUludGVyc2VjdGlvbiwgc3RhcnRJbnNpZGUsIGludGVycG9sYXRlLCBzdHJlYW0pO1xuICAgICAgICB9XG4gICAgICAgIHN0cmVhbS5wb2x5Z29uRW5kKCk7XG4gICAgICB9XG4gICAgICBhY3RpdmVTdHJlYW0gPSBzdHJlYW0sIHNlZ21lbnRzID0gcG9seWdvbiA9IHJpbmcgPSBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpbmVTdGFydCgpIHtcbiAgICAgIGNsaXBTdHJlYW0ucG9pbnQgPSBsaW5lUG9pbnQ7XG4gICAgICBpZiAocG9seWdvbikgcG9seWdvbi5wdXNoKHJpbmcgPSBbXSk7XG4gICAgICBmaXJzdCA9IHRydWU7XG4gICAgICB2XyA9IGZhbHNlO1xuICAgICAgeF8gPSB5XyA9IE5hTjtcbiAgICB9XG5cbiAgICAvLyBUT0RPIHJhdGhlciB0aGFuIHNwZWNpYWwtY2FzZSBwb2x5Z29ucywgc2ltcGx5IGhhbmRsZSB0aGVtIHNlcGFyYXRlbHkuXG4gICAgLy8gSWRlYWxseSwgY29pbmNpZGVudCBpbnRlcnNlY3Rpb24gcG9pbnRzIHNob3VsZCBiZSBqaXR0ZXJlZCB0byBhdm9pZFxuICAgIC8vIGNsaXBwaW5nIGlzc3Vlcy5cbiAgICBmdW5jdGlvbiBsaW5lRW5kKCkge1xuICAgICAgaWYgKHNlZ21lbnRzKSB7XG4gICAgICAgIGxpbmVQb2ludCh4X18sIHlfXyk7XG4gICAgICAgIGlmICh2X18gJiYgdl8pIGJ1ZmZlclN0cmVhbS5yZWpvaW4oKTtcbiAgICAgICAgc2VnbWVudHMucHVzaChidWZmZXJTdHJlYW0ucmVzdWx0KCkpO1xuICAgICAgfVxuICAgICAgY2xpcFN0cmVhbS5wb2ludCA9IHBvaW50O1xuICAgICAgaWYgKHZfKSBhY3RpdmVTdHJlYW0ubGluZUVuZCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpbmVQb2ludCh4LCB5KSB7XG4gICAgICB2YXIgdiA9IHZpc2libGUoeCwgeSk7XG4gICAgICBpZiAocG9seWdvbikgcmluZy5wdXNoKFt4LCB5XSk7XG4gICAgICBpZiAoZmlyc3QpIHtcbiAgICAgICAgeF9fID0geCwgeV9fID0geSwgdl9fID0gdjtcbiAgICAgICAgZmlyc3QgPSBmYWxzZTtcbiAgICAgICAgaWYgKHYpIHtcbiAgICAgICAgICBhY3RpdmVTdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgICAgYWN0aXZlU3RyZWFtLnBvaW50KHgsIHkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodiAmJiB2XykgYWN0aXZlU3RyZWFtLnBvaW50KHgsIHkpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICB2YXIgYSA9IFt4XyA9IE1hdGgubWF4KGNsaXBNaW4sIE1hdGgubWluKGNsaXBNYXgsIHhfKSksIHlfID0gTWF0aC5tYXgoY2xpcE1pbiwgTWF0aC5taW4oY2xpcE1heCwgeV8pKV0sXG4gICAgICAgICAgICAgIGIgPSBbeCA9IE1hdGgubWF4KGNsaXBNaW4sIE1hdGgubWluKGNsaXBNYXgsIHgpKSwgeSA9IE1hdGgubWF4KGNsaXBNaW4sIE1hdGgubWluKGNsaXBNYXgsIHkpKV07XG4gICAgICAgICAgaWYgKGNsaXBMaW5lKGEsIGIsIHgwLCB5MCwgeDEsIHkxKSkge1xuICAgICAgICAgICAgaWYgKCF2Xykge1xuICAgICAgICAgICAgICBhY3RpdmVTdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICAgIGFjdGl2ZVN0cmVhbS5wb2ludChhWzBdLCBhWzFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFjdGl2ZVN0cmVhbS5wb2ludChiWzBdLCBiWzFdKTtcbiAgICAgICAgICAgIGlmICghdikgYWN0aXZlU3RyZWFtLmxpbmVFbmQoKTtcbiAgICAgICAgICAgIGNsZWFuID0gZmFsc2U7XG4gICAgICAgICAgfSBlbHNlIGlmICh2KSB7XG4gICAgICAgICAgICBhY3RpdmVTdHJlYW0ubGluZVN0YXJ0KCk7XG4gICAgICAgICAgICBhY3RpdmVTdHJlYW0ucG9pbnQoeCwgeSk7XG4gICAgICAgICAgICBjbGVhbiA9IGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgeF8gPSB4LCB5XyA9IHksIHZfID0gdjtcbiAgICB9XG5cbiAgICByZXR1cm4gY2xpcFN0cmVhbTtcbiAgfTtcbn1cblxudmFyIGV4dGVudCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgeDAgPSAwLFxuICAgICAgeTAgPSAwLFxuICAgICAgeDEgPSA5NjAsXG4gICAgICB5MSA9IDUwMCxcbiAgICAgIGNhY2hlLFxuICAgICAgY2FjaGVTdHJlYW0sXG4gICAgICBjbGlwO1xuXG4gIHJldHVybiBjbGlwID0ge1xuICAgIHN0cmVhbTogZnVuY3Rpb24oc3RyZWFtKSB7XG4gICAgICByZXR1cm4gY2FjaGUgJiYgY2FjaGVTdHJlYW0gPT09IHN0cmVhbSA/IGNhY2hlIDogY2FjaGUgPSBjbGlwUmVjdGFuZ2xlKHgwLCB5MCwgeDEsIHkxKShjYWNoZVN0cmVhbSA9IHN0cmVhbSk7XG4gICAgfSxcbiAgICBleHRlbnQ6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHgwID0gK19bMF1bMF0sIHkwID0gK19bMF1bMV0sIHgxID0gK19bMV1bMF0sIHkxID0gK19bMV1bMV0sIGNhY2hlID0gY2FjaGVTdHJlYW0gPSBudWxsLCBjbGlwKSA6IFtbeDAsIHkwXSwgW3gxLCB5MV1dO1xuICAgIH1cbiAgfTtcbn07XG5cbnZhciBsZW5ndGhTdW0gPSBhZGRlcigpO1xudmFyIGxhbWJkYTAkMjtcbnZhciBzaW5QaGkwJDE7XG52YXIgY29zUGhpMCQxO1xuXG52YXIgbGVuZ3RoU3RyZWFtID0ge1xuICBzcGhlcmU6IG5vb3AsXG4gIHBvaW50OiBub29wLFxuICBsaW5lU3RhcnQ6IGxlbmd0aExpbmVTdGFydCxcbiAgbGluZUVuZDogbm9vcCxcbiAgcG9seWdvblN0YXJ0OiBub29wLFxuICBwb2x5Z29uRW5kOiBub29wXG59O1xuXG5mdW5jdGlvbiBsZW5ndGhMaW5lU3RhcnQoKSB7XG4gIGxlbmd0aFN0cmVhbS5wb2ludCA9IGxlbmd0aFBvaW50Rmlyc3Q7XG4gIGxlbmd0aFN0cmVhbS5saW5lRW5kID0gbGVuZ3RoTGluZUVuZDtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoTGluZUVuZCgpIHtcbiAgbGVuZ3RoU3RyZWFtLnBvaW50ID0gbGVuZ3RoU3RyZWFtLmxpbmVFbmQgPSBub29wO1xufVxuXG5mdW5jdGlvbiBsZW5ndGhQb2ludEZpcnN0KGxhbWJkYSwgcGhpKSB7XG4gIGxhbWJkYSAqPSByYWRpYW5zLCBwaGkgKj0gcmFkaWFucztcbiAgbGFtYmRhMCQyID0gbGFtYmRhLCBzaW5QaGkwJDEgPSBzaW4ocGhpKSwgY29zUGhpMCQxID0gY29zKHBoaSk7XG4gIGxlbmd0aFN0cmVhbS5wb2ludCA9IGxlbmd0aFBvaW50O1xufVxuXG5mdW5jdGlvbiBsZW5ndGhQb2ludChsYW1iZGEsIHBoaSkge1xuICBsYW1iZGEgKj0gcmFkaWFucywgcGhpICo9IHJhZGlhbnM7XG4gIHZhciBzaW5QaGkgPSBzaW4ocGhpKSxcbiAgICAgIGNvc1BoaSA9IGNvcyhwaGkpLFxuICAgICAgZGVsdGEgPSBhYnMobGFtYmRhIC0gbGFtYmRhMCQyKSxcbiAgICAgIGNvc0RlbHRhID0gY29zKGRlbHRhKSxcbiAgICAgIHNpbkRlbHRhID0gc2luKGRlbHRhKSxcbiAgICAgIHggPSBjb3NQaGkgKiBzaW5EZWx0YSxcbiAgICAgIHkgPSBjb3NQaGkwJDEgKiBzaW5QaGkgLSBzaW5QaGkwJDEgKiBjb3NQaGkgKiBjb3NEZWx0YSxcbiAgICAgIHogPSBzaW5QaGkwJDEgKiBzaW5QaGkgKyBjb3NQaGkwJDEgKiBjb3NQaGkgKiBjb3NEZWx0YTtcbiAgbGVuZ3RoU3VtLmFkZChhdGFuMihzcXJ0KHggKiB4ICsgeSAqIHkpLCB6KSk7XG4gIGxhbWJkYTAkMiA9IGxhbWJkYSwgc2luUGhpMCQxID0gc2luUGhpLCBjb3NQaGkwJDEgPSBjb3NQaGk7XG59XG5cbnZhciBsZW5ndGggPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgbGVuZ3RoU3VtLnJlc2V0KCk7XG4gIGdlb1N0cmVhbShvYmplY3QsIGxlbmd0aFN0cmVhbSk7XG4gIHJldHVybiArbGVuZ3RoU3VtO1xufTtcblxudmFyIGNvb3JkaW5hdGVzID0gW251bGwsIG51bGxdO1xudmFyIG9iamVjdCA9IHt0eXBlOiBcIkxpbmVTdHJpbmdcIiwgY29vcmRpbmF0ZXM6IGNvb3JkaW5hdGVzfTtcblxudmFyIGRpc3RhbmNlID0gZnVuY3Rpb24oYSwgYikge1xuICBjb29yZGluYXRlc1swXSA9IGE7XG4gIGNvb3JkaW5hdGVzWzFdID0gYjtcbiAgcmV0dXJuIGxlbmd0aChvYmplY3QpO1xufTtcblxudmFyIGNvbnRhaW5zT2JqZWN0VHlwZSA9IHtcbiAgRmVhdHVyZTogZnVuY3Rpb24ob2JqZWN0LCBwb2ludCkge1xuICAgIHJldHVybiBjb250YWluc0dlb21ldHJ5KG9iamVjdC5nZW9tZXRyeSwgcG9pbnQpO1xuICB9LFxuICBGZWF0dXJlQ29sbGVjdGlvbjogZnVuY3Rpb24ob2JqZWN0LCBwb2ludCkge1xuICAgIHZhciBmZWF0dXJlcyA9IG9iamVjdC5mZWF0dXJlcywgaSA9IC0xLCBuID0gZmVhdHVyZXMubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoY29udGFpbnNHZW9tZXRyeShmZWF0dXJlc1tpXS5nZW9tZXRyeSwgcG9pbnQpKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbnZhciBjb250YWluc0dlb21ldHJ5VHlwZSA9IHtcbiAgU3BoZXJlOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcbiAgUG9pbnQ6IGZ1bmN0aW9uKG9iamVjdCwgcG9pbnQpIHtcbiAgICByZXR1cm4gY29udGFpbnNQb2ludChvYmplY3QuY29vcmRpbmF0ZXMsIHBvaW50KTtcbiAgfSxcbiAgTXVsdGlQb2ludDogZnVuY3Rpb24ob2JqZWN0LCBwb2ludCkge1xuICAgIHZhciBjb29yZGluYXRlcyA9IG9iamVjdC5jb29yZGluYXRlcywgaSA9IC0xLCBuID0gY29vcmRpbmF0ZXMubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoY29udGFpbnNQb2ludChjb29yZGluYXRlc1tpXSwgcG9pbnQpKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG4gIExpbmVTdHJpbmc6IGZ1bmN0aW9uKG9iamVjdCwgcG9pbnQpIHtcbiAgICByZXR1cm4gY29udGFpbnNMaW5lKG9iamVjdC5jb29yZGluYXRlcywgcG9pbnQpO1xuICB9LFxuICBNdWx0aUxpbmVTdHJpbmc6IGZ1bmN0aW9uKG9iamVjdCwgcG9pbnQpIHtcbiAgICB2YXIgY29vcmRpbmF0ZXMgPSBvYmplY3QuY29vcmRpbmF0ZXMsIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgaWYgKGNvbnRhaW5zTGluZShjb29yZGluYXRlc1tpXSwgcG9pbnQpKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG4gIFBvbHlnb246IGZ1bmN0aW9uKG9iamVjdCwgcG9pbnQpIHtcbiAgICByZXR1cm4gY29udGFpbnNQb2x5Z29uKG9iamVjdC5jb29yZGluYXRlcywgcG9pbnQpO1xuICB9LFxuICBNdWx0aVBvbHlnb246IGZ1bmN0aW9uKG9iamVjdCwgcG9pbnQpIHtcbiAgICB2YXIgY29vcmRpbmF0ZXMgPSBvYmplY3QuY29vcmRpbmF0ZXMsIGkgPSAtMSwgbiA9IGNvb3JkaW5hdGVzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgaWYgKGNvbnRhaW5zUG9seWdvbihjb29yZGluYXRlc1tpXSwgcG9pbnQpKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG4gIEdlb21ldHJ5Q29sbGVjdGlvbjogZnVuY3Rpb24ob2JqZWN0LCBwb2ludCkge1xuICAgIHZhciBnZW9tZXRyaWVzID0gb2JqZWN0Lmdlb21ldHJpZXMsIGkgPSAtMSwgbiA9IGdlb21ldHJpZXMubGVuZ3RoO1xuICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoY29udGFpbnNHZW9tZXRyeShnZW9tZXRyaWVzW2ldLCBwb2ludCkpIHJldHVybiB0cnVlO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuZnVuY3Rpb24gY29udGFpbnNHZW9tZXRyeShnZW9tZXRyeSwgcG9pbnQpIHtcbiAgcmV0dXJuIGdlb21ldHJ5ICYmIGNvbnRhaW5zR2VvbWV0cnlUeXBlLmhhc093blByb3BlcnR5KGdlb21ldHJ5LnR5cGUpXG4gICAgICA/IGNvbnRhaW5zR2VvbWV0cnlUeXBlW2dlb21ldHJ5LnR5cGVdKGdlb21ldHJ5LCBwb2ludClcbiAgICAgIDogZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zUG9pbnQoY29vcmRpbmF0ZXMsIHBvaW50KSB7XG4gIHJldHVybiBkaXN0YW5jZShjb29yZGluYXRlcywgcG9pbnQpID09PSAwO1xufVxuXG5mdW5jdGlvbiBjb250YWluc0xpbmUoY29vcmRpbmF0ZXMsIHBvaW50KSB7XG4gIHZhciBhYiA9IGRpc3RhbmNlKGNvb3JkaW5hdGVzWzBdLCBjb29yZGluYXRlc1sxXSksXG4gICAgICBhbyA9IGRpc3RhbmNlKGNvb3JkaW5hdGVzWzBdLCBwb2ludCksXG4gICAgICBvYiA9IGRpc3RhbmNlKHBvaW50LCBjb29yZGluYXRlc1sxXSk7XG4gIHJldHVybiBhbyArIG9iIDw9IGFiICsgZXBzaWxvbjtcbn1cblxuZnVuY3Rpb24gY29udGFpbnNQb2x5Z29uKGNvb3JkaW5hdGVzLCBwb2ludCkge1xuICByZXR1cm4gISFwb2x5Z29uQ29udGFpbnMoY29vcmRpbmF0ZXMubWFwKHJpbmdSYWRpYW5zKSwgcG9pbnRSYWRpYW5zKHBvaW50KSk7XG59XG5cbmZ1bmN0aW9uIHJpbmdSYWRpYW5zKHJpbmcpIHtcbiAgcmV0dXJuIHJpbmcgPSByaW5nLm1hcChwb2ludFJhZGlhbnMpLCByaW5nLnBvcCgpLCByaW5nO1xufVxuXG5mdW5jdGlvbiBwb2ludFJhZGlhbnMocG9pbnQpIHtcbiAgcmV0dXJuIFtwb2ludFswXSAqIHJhZGlhbnMsIHBvaW50WzFdICogcmFkaWFuc107XG59XG5cbnZhciBjb250YWlucyA9IGZ1bmN0aW9uKG9iamVjdCwgcG9pbnQpIHtcbiAgcmV0dXJuIChvYmplY3QgJiYgY29udGFpbnNPYmplY3RUeXBlLmhhc093blByb3BlcnR5KG9iamVjdC50eXBlKVxuICAgICAgPyBjb250YWluc09iamVjdFR5cGVbb2JqZWN0LnR5cGVdXG4gICAgICA6IGNvbnRhaW5zR2VvbWV0cnkpKG9iamVjdCwgcG9pbnQpO1xufTtcblxuZnVuY3Rpb24gZ3JhdGljdWxlWCh5MCwgeTEsIGR5KSB7XG4gIHZhciB5ID0gZDNBcnJheS5yYW5nZSh5MCwgeTEgLSBlcHNpbG9uLCBkeSkuY29uY2F0KHkxKTtcbiAgcmV0dXJuIGZ1bmN0aW9uKHgpIHsgcmV0dXJuIHkubWFwKGZ1bmN0aW9uKHkpIHsgcmV0dXJuIFt4LCB5XTsgfSk7IH07XG59XG5cbmZ1bmN0aW9uIGdyYXRpY3VsZVkoeDAsIHgxLCBkeCkge1xuICB2YXIgeCA9IGQzQXJyYXkucmFuZ2UoeDAsIHgxIC0gZXBzaWxvbiwgZHgpLmNvbmNhdCh4MSk7XG4gIHJldHVybiBmdW5jdGlvbih5KSB7IHJldHVybiB4Lm1hcChmdW5jdGlvbih4KSB7IHJldHVybiBbeCwgeV07IH0pOyB9O1xufVxuXG5mdW5jdGlvbiBncmF0aWN1bGUoKSB7XG4gIHZhciB4MSwgeDAsIFgxLCBYMCxcbiAgICAgIHkxLCB5MCwgWTEsIFkwLFxuICAgICAgZHggPSAxMCwgZHkgPSBkeCwgRFggPSA5MCwgRFkgPSAzNjAsXG4gICAgICB4LCB5LCBYLCBZLFxuICAgICAgcHJlY2lzaW9uID0gMi41O1xuXG4gIGZ1bmN0aW9uIGdyYXRpY3VsZSgpIHtcbiAgICByZXR1cm4ge3R5cGU6IFwiTXVsdGlMaW5lU3RyaW5nXCIsIGNvb3JkaW5hdGVzOiBsaW5lcygpfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGxpbmVzKCkge1xuICAgIHJldHVybiBkM0FycmF5LnJhbmdlKGNlaWwoWDAgLyBEWCkgKiBEWCwgWDEsIERYKS5tYXAoWClcbiAgICAgICAgLmNvbmNhdChkM0FycmF5LnJhbmdlKGNlaWwoWTAgLyBEWSkgKiBEWSwgWTEsIERZKS5tYXAoWSkpXG4gICAgICAgIC5jb25jYXQoZDNBcnJheS5yYW5nZShjZWlsKHgwIC8gZHgpICogZHgsIHgxLCBkeCkuZmlsdGVyKGZ1bmN0aW9uKHgpIHsgcmV0dXJuIGFicyh4ICUgRFgpID4gZXBzaWxvbjsgfSkubWFwKHgpKVxuICAgICAgICAuY29uY2F0KGQzQXJyYXkucmFuZ2UoY2VpbCh5MCAvIGR5KSAqIGR5LCB5MSwgZHkpLmZpbHRlcihmdW5jdGlvbih5KSB7IHJldHVybiBhYnMoeSAlIERZKSA+IGVwc2lsb247IH0pLm1hcCh5KSk7XG4gIH1cblxuICBncmF0aWN1bGUubGluZXMgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gbGluZXMoKS5tYXAoZnVuY3Rpb24oY29vcmRpbmF0ZXMpIHsgcmV0dXJuIHt0eXBlOiBcIkxpbmVTdHJpbmdcIiwgY29vcmRpbmF0ZXM6IGNvb3JkaW5hdGVzfTsgfSk7XG4gIH07XG5cbiAgZ3JhdGljdWxlLm91dGxpbmUgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogXCJQb2x5Z29uXCIsXG4gICAgICBjb29yZGluYXRlczogW1xuICAgICAgICBYKFgwKS5jb25jYXQoXG4gICAgICAgIFkoWTEpLnNsaWNlKDEpLFxuICAgICAgICBYKFgxKS5yZXZlcnNlKCkuc2xpY2UoMSksXG4gICAgICAgIFkoWTApLnJldmVyc2UoKS5zbGljZSgxKSlcbiAgICAgIF1cbiAgICB9O1xuICB9O1xuXG4gIGdyYXRpY3VsZS5leHRlbnQgPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZ3JhdGljdWxlLmV4dGVudE1pbm9yKCk7XG4gICAgcmV0dXJuIGdyYXRpY3VsZS5leHRlbnRNYWpvcihfKS5leHRlbnRNaW5vcihfKTtcbiAgfTtcblxuICBncmF0aWN1bGUuZXh0ZW50TWFqb3IgPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gW1tYMCwgWTBdLCBbWDEsIFkxXV07XG4gICAgWDAgPSArX1swXVswXSwgWDEgPSArX1sxXVswXTtcbiAgICBZMCA9ICtfWzBdWzFdLCBZMSA9ICtfWzFdWzFdO1xuICAgIGlmIChYMCA+IFgxKSBfID0gWDAsIFgwID0gWDEsIFgxID0gXztcbiAgICBpZiAoWTAgPiBZMSkgXyA9IFkwLCBZMCA9IFkxLCBZMSA9IF87XG4gICAgcmV0dXJuIGdyYXRpY3VsZS5wcmVjaXNpb24ocHJlY2lzaW9uKTtcbiAgfTtcblxuICBncmF0aWN1bGUuZXh0ZW50TWlub3IgPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gW1t4MCwgeTBdLCBbeDEsIHkxXV07XG4gICAgeDAgPSArX1swXVswXSwgeDEgPSArX1sxXVswXTtcbiAgICB5MCA9ICtfWzBdWzFdLCB5MSA9ICtfWzFdWzFdO1xuICAgIGlmICh4MCA+IHgxKSBfID0geDAsIHgwID0geDEsIHgxID0gXztcbiAgICBpZiAoeTAgPiB5MSkgXyA9IHkwLCB5MCA9IHkxLCB5MSA9IF87XG4gICAgcmV0dXJuIGdyYXRpY3VsZS5wcmVjaXNpb24ocHJlY2lzaW9uKTtcbiAgfTtcblxuICBncmF0aWN1bGUuc3RlcCA9IGZ1bmN0aW9uKF8pIHtcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBncmF0aWN1bGUuc3RlcE1pbm9yKCk7XG4gICAgcmV0dXJuIGdyYXRpY3VsZS5zdGVwTWFqb3IoXykuc3RlcE1pbm9yKF8pO1xuICB9O1xuXG4gIGdyYXRpY3VsZS5zdGVwTWFqb3IgPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gW0RYLCBEWV07XG4gICAgRFggPSArX1swXSwgRFkgPSArX1sxXTtcbiAgICByZXR1cm4gZ3JhdGljdWxlO1xuICB9O1xuXG4gIGdyYXRpY3VsZS5zdGVwTWlub3IgPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gW2R4LCBkeV07XG4gICAgZHggPSArX1swXSwgZHkgPSArX1sxXTtcbiAgICByZXR1cm4gZ3JhdGljdWxlO1xuICB9O1xuXG4gIGdyYXRpY3VsZS5wcmVjaXNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcHJlY2lzaW9uO1xuICAgIHByZWNpc2lvbiA9ICtfO1xuICAgIHggPSBncmF0aWN1bGVYKHkwLCB5MSwgOTApO1xuICAgIHkgPSBncmF0aWN1bGVZKHgwLCB4MSwgcHJlY2lzaW9uKTtcbiAgICBYID0gZ3JhdGljdWxlWChZMCwgWTEsIDkwKTtcbiAgICBZID0gZ3JhdGljdWxlWShYMCwgWDEsIHByZWNpc2lvbik7XG4gICAgcmV0dXJuIGdyYXRpY3VsZTtcbiAgfTtcblxuICByZXR1cm4gZ3JhdGljdWxlXG4gICAgICAuZXh0ZW50TWFqb3IoW1stMTgwLCAtOTAgKyBlcHNpbG9uXSwgWzE4MCwgOTAgLSBlcHNpbG9uXV0pXG4gICAgICAuZXh0ZW50TWlub3IoW1stMTgwLCAtODAgLSBlcHNpbG9uXSwgWzE4MCwgODAgKyBlcHNpbG9uXV0pO1xufVxuXG5mdW5jdGlvbiBncmF0aWN1bGUxMCgpIHtcbiAgcmV0dXJuIGdyYXRpY3VsZSgpKCk7XG59XG5cbnZhciBpbnRlcnBvbGF0ZSA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgdmFyIHgwID0gYVswXSAqIHJhZGlhbnMsXG4gICAgICB5MCA9IGFbMV0gKiByYWRpYW5zLFxuICAgICAgeDEgPSBiWzBdICogcmFkaWFucyxcbiAgICAgIHkxID0gYlsxXSAqIHJhZGlhbnMsXG4gICAgICBjeTAgPSBjb3MoeTApLFxuICAgICAgc3kwID0gc2luKHkwKSxcbiAgICAgIGN5MSA9IGNvcyh5MSksXG4gICAgICBzeTEgPSBzaW4oeTEpLFxuICAgICAga3gwID0gY3kwICogY29zKHgwKSxcbiAgICAgIGt5MCA9IGN5MCAqIHNpbih4MCksXG4gICAgICBreDEgPSBjeTEgKiBjb3MoeDEpLFxuICAgICAga3kxID0gY3kxICogc2luKHgxKSxcbiAgICAgIGQgPSAyICogYXNpbihzcXJ0KGhhdmVyc2luKHkxIC0geTApICsgY3kwICogY3kxICogaGF2ZXJzaW4oeDEgLSB4MCkpKSxcbiAgICAgIGsgPSBzaW4oZCk7XG5cbiAgdmFyIGludGVycG9sYXRlID0gZCA/IGZ1bmN0aW9uKHQpIHtcbiAgICB2YXIgQiA9IHNpbih0ICo9IGQpIC8gayxcbiAgICAgICAgQSA9IHNpbihkIC0gdCkgLyBrLFxuICAgICAgICB4ID0gQSAqIGt4MCArIEIgKiBreDEsXG4gICAgICAgIHkgPSBBICoga3kwICsgQiAqIGt5MSxcbiAgICAgICAgeiA9IEEgKiBzeTAgKyBCICogc3kxO1xuICAgIHJldHVybiBbXG4gICAgICBhdGFuMih5LCB4KSAqIGRlZ3JlZXMsXG4gICAgICBhdGFuMih6LCBzcXJ0KHggKiB4ICsgeSAqIHkpKSAqIGRlZ3JlZXNcbiAgICBdO1xuICB9IDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIFt4MCAqIGRlZ3JlZXMsIHkwICogZGVncmVlc107XG4gIH07XG5cbiAgaW50ZXJwb2xhdGUuZGlzdGFuY2UgPSBkO1xuXG4gIHJldHVybiBpbnRlcnBvbGF0ZTtcbn07XG5cbnZhciBpZGVudGl0eSA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHg7XG59O1xuXG52YXIgYXJlYVN1bSQxID0gYWRkZXIoKTtcbnZhciBhcmVhUmluZ1N1bSQxID0gYWRkZXIoKTtcbnZhciB4MDA7XG52YXIgeTAwO1xudmFyIHgwJDE7XG52YXIgeTAkMTtcblxudmFyIGFyZWFTdHJlYW0kMSA9IHtcbiAgcG9pbnQ6IG5vb3AsXG4gIGxpbmVTdGFydDogbm9vcCxcbiAgbGluZUVuZDogbm9vcCxcbiAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICBhcmVhU3RyZWFtJDEubGluZVN0YXJ0ID0gYXJlYVJpbmdTdGFydCQxO1xuICAgIGFyZWFTdHJlYW0kMS5saW5lRW5kID0gYXJlYVJpbmdFbmQkMTtcbiAgfSxcbiAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgYXJlYVN0cmVhbSQxLmxpbmVTdGFydCA9IGFyZWFTdHJlYW0kMS5saW5lRW5kID0gYXJlYVN0cmVhbSQxLnBvaW50ID0gbm9vcDtcbiAgICBhcmVhU3VtJDEuYWRkKGFicyhhcmVhUmluZ1N1bSQxKSk7XG4gICAgYXJlYVJpbmdTdW0kMS5yZXNldCgpO1xuICB9LFxuICByZXN1bHQ6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmVhID0gYXJlYVN1bSQxIC8gMjtcbiAgICBhcmVhU3VtJDEucmVzZXQoKTtcbiAgICByZXR1cm4gYXJlYTtcbiAgfVxufTtcblxuZnVuY3Rpb24gYXJlYVJpbmdTdGFydCQxKCkge1xuICBhcmVhU3RyZWFtJDEucG9pbnQgPSBhcmVhUG9pbnRGaXJzdCQxO1xufVxuXG5mdW5jdGlvbiBhcmVhUG9pbnRGaXJzdCQxKHgsIHkpIHtcbiAgYXJlYVN0cmVhbSQxLnBvaW50ID0gYXJlYVBvaW50JDE7XG4gIHgwMCA9IHgwJDEgPSB4LCB5MDAgPSB5MCQxID0geTtcbn1cblxuZnVuY3Rpb24gYXJlYVBvaW50JDEoeCwgeSkge1xuICBhcmVhUmluZ1N1bSQxLmFkZCh5MCQxICogeCAtIHgwJDEgKiB5KTtcbiAgeDAkMSA9IHgsIHkwJDEgPSB5O1xufVxuXG5mdW5jdGlvbiBhcmVhUmluZ0VuZCQxKCkge1xuICBhcmVhUG9pbnQkMSh4MDAsIHkwMCk7XG59XG5cbnZhciB4MCQyID0gSW5maW5pdHk7XG52YXIgeTAkMiA9IHgwJDI7XG52YXIgeDEgPSAteDAkMjtcbnZhciB5MSA9IHgxO1xuXG52YXIgYm91bmRzU3RyZWFtJDEgPSB7XG4gIHBvaW50OiBib3VuZHNQb2ludCQxLFxuICBsaW5lU3RhcnQ6IG5vb3AsXG4gIGxpbmVFbmQ6IG5vb3AsXG4gIHBvbHlnb25TdGFydDogbm9vcCxcbiAgcG9seWdvbkVuZDogbm9vcCxcbiAgcmVzdWx0OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgYm91bmRzID0gW1t4MCQyLCB5MCQyXSwgW3gxLCB5MV1dO1xuICAgIHgxID0geTEgPSAtKHkwJDIgPSB4MCQyID0gSW5maW5pdHkpO1xuICAgIHJldHVybiBib3VuZHM7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGJvdW5kc1BvaW50JDEoeCwgeSkge1xuICBpZiAoeCA8IHgwJDIpIHgwJDIgPSB4O1xuICBpZiAoeCA+IHgxKSB4MSA9IHg7XG4gIGlmICh5IDwgeTAkMikgeTAkMiA9IHk7XG4gIGlmICh5ID4geTEpIHkxID0geTtcbn1cblxuLy8gVE9ETyBFbmZvcmNlIHBvc2l0aXZlIGFyZWEgZm9yIGV4dGVyaW9yLCBuZWdhdGl2ZSBhcmVhIGZvciBpbnRlcmlvcj9cblxudmFyIFgwJDEgPSAwO1xudmFyIFkwJDEgPSAwO1xudmFyIFowJDEgPSAwO1xudmFyIFgxJDEgPSAwO1xudmFyIFkxJDEgPSAwO1xudmFyIFoxJDEgPSAwO1xudmFyIFgyJDEgPSAwO1xudmFyIFkyJDEgPSAwO1xudmFyIFoyJDEgPSAwO1xudmFyIHgwMCQxO1xudmFyIHkwMCQxO1xudmFyIHgwJDM7XG52YXIgeTAkMztcblxudmFyIGNlbnRyb2lkU3RyZWFtJDEgPSB7XG4gIHBvaW50OiBjZW50cm9pZFBvaW50JDEsXG4gIGxpbmVTdGFydDogY2VudHJvaWRMaW5lU3RhcnQkMSxcbiAgbGluZUVuZDogY2VudHJvaWRMaW5lRW5kJDEsXG4gIHBvbHlnb25TdGFydDogZnVuY3Rpb24oKSB7XG4gICAgY2VudHJvaWRTdHJlYW0kMS5saW5lU3RhcnQgPSBjZW50cm9pZFJpbmdTdGFydCQxO1xuICAgIGNlbnRyb2lkU3RyZWFtJDEubGluZUVuZCA9IGNlbnRyb2lkUmluZ0VuZCQxO1xuICB9LFxuICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICBjZW50cm9pZFN0cmVhbSQxLnBvaW50ID0gY2VudHJvaWRQb2ludCQxO1xuICAgIGNlbnRyb2lkU3RyZWFtJDEubGluZVN0YXJ0ID0gY2VudHJvaWRMaW5lU3RhcnQkMTtcbiAgICBjZW50cm9pZFN0cmVhbSQxLmxpbmVFbmQgPSBjZW50cm9pZExpbmVFbmQkMTtcbiAgfSxcbiAgcmVzdWx0OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgY2VudHJvaWQgPSBaMiQxID8gW1gyJDEgLyBaMiQxLCBZMiQxIC8gWjIkMV1cbiAgICAgICAgOiBaMSQxID8gW1gxJDEgLyBaMSQxLCBZMSQxIC8gWjEkMV1cbiAgICAgICAgOiBaMCQxID8gW1gwJDEgLyBaMCQxLCBZMCQxIC8gWjAkMV1cbiAgICAgICAgOiBbTmFOLCBOYU5dO1xuICAgIFgwJDEgPSBZMCQxID0gWjAkMSA9XG4gICAgWDEkMSA9IFkxJDEgPSBaMSQxID1cbiAgICBYMiQxID0gWTIkMSA9IFoyJDEgPSAwO1xuICAgIHJldHVybiBjZW50cm9pZDtcbiAgfVxufTtcblxuZnVuY3Rpb24gY2VudHJvaWRQb2ludCQxKHgsIHkpIHtcbiAgWDAkMSArPSB4O1xuICBZMCQxICs9IHk7XG4gICsrWjAkMTtcbn1cblxuZnVuY3Rpb24gY2VudHJvaWRMaW5lU3RhcnQkMSgpIHtcbiAgY2VudHJvaWRTdHJlYW0kMS5wb2ludCA9IGNlbnRyb2lkUG9pbnRGaXJzdExpbmU7XG59XG5cbmZ1bmN0aW9uIGNlbnRyb2lkUG9pbnRGaXJzdExpbmUoeCwgeSkge1xuICBjZW50cm9pZFN0cmVhbSQxLnBvaW50ID0gY2VudHJvaWRQb2ludExpbmU7XG4gIGNlbnRyb2lkUG9pbnQkMSh4MCQzID0geCwgeTAkMyA9IHkpO1xufVxuXG5mdW5jdGlvbiBjZW50cm9pZFBvaW50TGluZSh4LCB5KSB7XG4gIHZhciBkeCA9IHggLSB4MCQzLCBkeSA9IHkgLSB5MCQzLCB6ID0gc3FydChkeCAqIGR4ICsgZHkgKiBkeSk7XG4gIFgxJDEgKz0geiAqICh4MCQzICsgeCkgLyAyO1xuICBZMSQxICs9IHogKiAoeTAkMyArIHkpIC8gMjtcbiAgWjEkMSArPSB6O1xuICBjZW50cm9pZFBvaW50JDEoeDAkMyA9IHgsIHkwJDMgPSB5KTtcbn1cblxuZnVuY3Rpb24gY2VudHJvaWRMaW5lRW5kJDEoKSB7XG4gIGNlbnRyb2lkU3RyZWFtJDEucG9pbnQgPSBjZW50cm9pZFBvaW50JDE7XG59XG5cbmZ1bmN0aW9uIGNlbnRyb2lkUmluZ1N0YXJ0JDEoKSB7XG4gIGNlbnRyb2lkU3RyZWFtJDEucG9pbnQgPSBjZW50cm9pZFBvaW50Rmlyc3RSaW5nO1xufVxuXG5mdW5jdGlvbiBjZW50cm9pZFJpbmdFbmQkMSgpIHtcbiAgY2VudHJvaWRQb2ludFJpbmcoeDAwJDEsIHkwMCQxKTtcbn1cblxuZnVuY3Rpb24gY2VudHJvaWRQb2ludEZpcnN0UmluZyh4LCB5KSB7XG4gIGNlbnRyb2lkU3RyZWFtJDEucG9pbnQgPSBjZW50cm9pZFBvaW50UmluZztcbiAgY2VudHJvaWRQb2ludCQxKHgwMCQxID0geDAkMyA9IHgsIHkwMCQxID0geTAkMyA9IHkpO1xufVxuXG5mdW5jdGlvbiBjZW50cm9pZFBvaW50UmluZyh4LCB5KSB7XG4gIHZhciBkeCA9IHggLSB4MCQzLFxuICAgICAgZHkgPSB5IC0geTAkMyxcbiAgICAgIHogPSBzcXJ0KGR4ICogZHggKyBkeSAqIGR5KTtcblxuICBYMSQxICs9IHogKiAoeDAkMyArIHgpIC8gMjtcbiAgWTEkMSArPSB6ICogKHkwJDMgKyB5KSAvIDI7XG4gIFoxJDEgKz0gejtcblxuICB6ID0geTAkMyAqIHggLSB4MCQzICogeTtcbiAgWDIkMSArPSB6ICogKHgwJDMgKyB4KTtcbiAgWTIkMSArPSB6ICogKHkwJDMgKyB5KTtcbiAgWjIkMSArPSB6ICogMztcbiAgY2VudHJvaWRQb2ludCQxKHgwJDMgPSB4LCB5MCQzID0geSk7XG59XG5cbmZ1bmN0aW9uIFBhdGhDb250ZXh0KGNvbnRleHQpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG59XG5cblBhdGhDb250ZXh0LnByb3RvdHlwZSA9IHtcbiAgX3JhZGl1czogNC41LFxuICBwb2ludFJhZGl1czogZnVuY3Rpb24oXykge1xuICAgIHJldHVybiB0aGlzLl9yYWRpdXMgPSBfLCB0aGlzO1xuICB9LFxuICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuX2xpbmUgPT09IDApIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgdGhpcy5fcG9pbnQgPSBOYU47XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAwOiB7XG4gICAgICAgIHRoaXMuX2NvbnRleHQubW92ZVRvKHgsIHkpO1xuICAgICAgICB0aGlzLl9wb2ludCA9IDE7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAxOiB7XG4gICAgICAgIHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGRlZmF1bHQ6IHtcbiAgICAgICAgdGhpcy5fY29udGV4dC5tb3ZlVG8oeCArIHRoaXMuX3JhZGl1cywgeSk7XG4gICAgICAgIHRoaXMuX2NvbnRleHQuYXJjKHgsIHksIHRoaXMuX3JhZGl1cywgMCwgdGF1KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICByZXN1bHQ6IG5vb3Bcbn07XG5cbnZhciBsZW5ndGhTdW0kMSA9IGFkZGVyKCk7XG52YXIgbGVuZ3RoUmluZztcbnZhciB4MDAkMjtcbnZhciB5MDAkMjtcbnZhciB4MCQ0O1xudmFyIHkwJDQ7XG5cbnZhciBsZW5ndGhTdHJlYW0kMSA9IHtcbiAgcG9pbnQ6IG5vb3AsXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgbGVuZ3RoU3RyZWFtJDEucG9pbnQgPSBsZW5ndGhQb2ludEZpcnN0JDE7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmIChsZW5ndGhSaW5nKSBsZW5ndGhQb2ludCQxKHgwMCQyLCB5MDAkMik7XG4gICAgbGVuZ3RoU3RyZWFtJDEucG9pbnQgPSBub29wO1xuICB9LFxuICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIGxlbmd0aFJpbmcgPSB0cnVlO1xuICB9LFxuICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHtcbiAgICBsZW5ndGhSaW5nID0gbnVsbDtcbiAgfSxcbiAgcmVzdWx0OiBmdW5jdGlvbigpIHtcbiAgICB2YXIgbGVuZ3RoID0gK2xlbmd0aFN1bSQxO1xuICAgIGxlbmd0aFN1bSQxLnJlc2V0KCk7XG4gICAgcmV0dXJuIGxlbmd0aDtcbiAgfVxufTtcblxuZnVuY3Rpb24gbGVuZ3RoUG9pbnRGaXJzdCQxKHgsIHkpIHtcbiAgbGVuZ3RoU3RyZWFtJDEucG9pbnQgPSBsZW5ndGhQb2ludCQxO1xuICB4MDAkMiA9IHgwJDQgPSB4LCB5MDAkMiA9IHkwJDQgPSB5O1xufVxuXG5mdW5jdGlvbiBsZW5ndGhQb2ludCQxKHgsIHkpIHtcbiAgeDAkNCAtPSB4LCB5MCQ0IC09IHk7XG4gIGxlbmd0aFN1bSQxLmFkZChzcXJ0KHgwJDQgKiB4MCQ0ICsgeTAkNCAqIHkwJDQpKTtcbiAgeDAkNCA9IHgsIHkwJDQgPSB5O1xufVxuXG5mdW5jdGlvbiBQYXRoU3RyaW5nKCkge1xuICB0aGlzLl9zdHJpbmcgPSBbXTtcbn1cblxuUGF0aFN0cmluZy5wcm90b3R5cGUgPSB7XG4gIF9yYWRpdXM6IDQuNSxcbiAgX2NpcmNsZTogY2lyY2xlJDEoNC41KSxcbiAgcG9pbnRSYWRpdXM6IGZ1bmN0aW9uKF8pIHtcbiAgICBpZiAoKF8gPSArXykgIT09IHRoaXMuX3JhZGl1cykgdGhpcy5fcmFkaXVzID0gXywgdGhpcy5fY2lyY2xlID0gbnVsbDtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gMDtcbiAgfSxcbiAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IE5hTjtcbiAgfSxcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl9saW5lID09PSAwKSB0aGlzLl9zdHJpbmcucHVzaChcIlpcIik7XG4gICAgdGhpcy5fcG9pbnQgPSBOYU47XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAwOiB7XG4gICAgICAgIHRoaXMuX3N0cmluZy5wdXNoKFwiTVwiLCB4LCBcIixcIiwgeSk7XG4gICAgICAgIHRoaXMuX3BvaW50ID0gMTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDE6IHtcbiAgICAgICAgdGhpcy5fc3RyaW5nLnB1c2goXCJMXCIsIHgsIFwiLFwiLCB5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIGlmICh0aGlzLl9jaXJjbGUgPT0gbnVsbCkgdGhpcy5fY2lyY2xlID0gY2lyY2xlJDEodGhpcy5fcmFkaXVzKTtcbiAgICAgICAgdGhpcy5fc3RyaW5nLnB1c2goXCJNXCIsIHgsIFwiLFwiLCB5LCB0aGlzLl9jaXJjbGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIHJlc3VsdDogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuX3N0cmluZy5sZW5ndGgpIHtcbiAgICAgIHZhciByZXN1bHQgPSB0aGlzLl9zdHJpbmcuam9pbihcIlwiKTtcbiAgICAgIHRoaXMuX3N0cmluZyA9IFtdO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9XG59O1xuXG5mdW5jdGlvbiBjaXJjbGUkMShyYWRpdXMpIHtcbiAgcmV0dXJuIFwibTAsXCIgKyByYWRpdXNcbiAgICAgICsgXCJhXCIgKyByYWRpdXMgKyBcIixcIiArIHJhZGl1cyArIFwiIDAgMSwxIDAsXCIgKyAtMiAqIHJhZGl1c1xuICAgICAgKyBcImFcIiArIHJhZGl1cyArIFwiLFwiICsgcmFkaXVzICsgXCIgMCAxLDEgMCxcIiArIDIgKiByYWRpdXNcbiAgICAgICsgXCJ6XCI7XG59XG5cbnZhciBpbmRleCA9IGZ1bmN0aW9uKHByb2plY3Rpb24sIGNvbnRleHQpIHtcbiAgdmFyIHBvaW50UmFkaXVzID0gNC41LFxuICAgICAgcHJvamVjdGlvblN0cmVhbSxcbiAgICAgIGNvbnRleHRTdHJlYW07XG5cbiAgZnVuY3Rpb24gcGF0aChvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0KSB7XG4gICAgICBpZiAodHlwZW9mIHBvaW50UmFkaXVzID09PSBcImZ1bmN0aW9uXCIpIGNvbnRleHRTdHJlYW0ucG9pbnRSYWRpdXMoK3BvaW50UmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xuICAgICAgZ2VvU3RyZWFtKG9iamVjdCwgcHJvamVjdGlvblN0cmVhbShjb250ZXh0U3RyZWFtKSk7XG4gICAgfVxuICAgIHJldHVybiBjb250ZXh0U3RyZWFtLnJlc3VsdCgpO1xuICB9XG5cbiAgcGF0aC5hcmVhID0gZnVuY3Rpb24ob2JqZWN0KSB7XG4gICAgZ2VvU3RyZWFtKG9iamVjdCwgcHJvamVjdGlvblN0cmVhbShhcmVhU3RyZWFtJDEpKTtcbiAgICByZXR1cm4gYXJlYVN0cmVhbSQxLnJlc3VsdCgpO1xuICB9O1xuXG4gIHBhdGgubWVhc3VyZSA9IGZ1bmN0aW9uKG9iamVjdCkge1xuICAgIGdlb1N0cmVhbShvYmplY3QsIHByb2plY3Rpb25TdHJlYW0obGVuZ3RoU3RyZWFtJDEpKTtcbiAgICByZXR1cm4gbGVuZ3RoU3RyZWFtJDEucmVzdWx0KCk7XG4gIH07XG5cbiAgcGF0aC5ib3VuZHMgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBnZW9TdHJlYW0ob2JqZWN0LCBwcm9qZWN0aW9uU3RyZWFtKGJvdW5kc1N0cmVhbSQxKSk7XG4gICAgcmV0dXJuIGJvdW5kc1N0cmVhbSQxLnJlc3VsdCgpO1xuICB9O1xuXG4gIHBhdGguY2VudHJvaWQgPSBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBnZW9TdHJlYW0ob2JqZWN0LCBwcm9qZWN0aW9uU3RyZWFtKGNlbnRyb2lkU3RyZWFtJDEpKTtcbiAgICByZXR1cm4gY2VudHJvaWRTdHJlYW0kMS5yZXN1bHQoKTtcbiAgfTtcblxuICBwYXRoLnByb2plY3Rpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocHJvamVjdGlvblN0cmVhbSA9IF8gPT0gbnVsbCA/IChwcm9qZWN0aW9uID0gbnVsbCwgaWRlbnRpdHkpIDogKHByb2plY3Rpb24gPSBfKS5zdHJlYW0sIHBhdGgpIDogcHJvamVjdGlvbjtcbiAgfTtcblxuICBwYXRoLmNvbnRleHQgPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gY29udGV4dDtcbiAgICBjb250ZXh0U3RyZWFtID0gXyA9PSBudWxsID8gKGNvbnRleHQgPSBudWxsLCBuZXcgUGF0aFN0cmluZykgOiBuZXcgUGF0aENvbnRleHQoY29udGV4dCA9IF8pO1xuICAgIGlmICh0eXBlb2YgcG9pbnRSYWRpdXMgIT09IFwiZnVuY3Rpb25cIikgY29udGV4dFN0cmVhbS5wb2ludFJhZGl1cyhwb2ludFJhZGl1cyk7XG4gICAgcmV0dXJuIHBhdGg7XG4gIH07XG5cbiAgcGF0aC5wb2ludFJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBwb2ludFJhZGl1cztcbiAgICBwb2ludFJhZGl1cyA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogKGNvbnRleHRTdHJlYW0ucG9pbnRSYWRpdXMoK18pLCArXyk7XG4gICAgcmV0dXJuIHBhdGg7XG4gIH07XG5cbiAgcmV0dXJuIHBhdGgucHJvamVjdGlvbihwcm9qZWN0aW9uKS5jb250ZXh0KGNvbnRleHQpO1xufTtcblxudmFyIHRyYW5zZm9ybSA9IGZ1bmN0aW9uKG1ldGhvZHMpIHtcbiAgcmV0dXJuIHtcbiAgICBzdHJlYW06IHRyYW5zZm9ybWVyKG1ldGhvZHMpXG4gIH07XG59O1xuXG5mdW5jdGlvbiB0cmFuc2Zvcm1lcihtZXRob2RzKSB7XG4gIHJldHVybiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICB2YXIgcyA9IG5ldyBUcmFuc2Zvcm1TdHJlYW07XG4gICAgZm9yICh2YXIga2V5IGluIG1ldGhvZHMpIHNba2V5XSA9IG1ldGhvZHNba2V5XTtcbiAgICBzLnN0cmVhbSA9IHN0cmVhbTtcbiAgICByZXR1cm4gcztcbiAgfTtcbn1cblxuZnVuY3Rpb24gVHJhbnNmb3JtU3RyZWFtKCkge31cblxuVHJhbnNmb3JtU3RyZWFtLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFRyYW5zZm9ybVN0cmVhbSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHsgdGhpcy5zdHJlYW0ucG9pbnQoeCwgeSk7IH0sXG4gIHNwaGVyZTogZnVuY3Rpb24oKSB7IHRoaXMuc3RyZWFtLnNwaGVyZSgpOyB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkgeyB0aGlzLnN0cmVhbS5saW5lU3RhcnQoKTsgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7IHRoaXMuc3RyZWFtLmxpbmVFbmQoKTsgfSxcbiAgcG9seWdvblN0YXJ0OiBmdW5jdGlvbigpIHsgdGhpcy5zdHJlYW0ucG9seWdvblN0YXJ0KCk7IH0sXG4gIHBvbHlnb25FbmQ6IGZ1bmN0aW9uKCkgeyB0aGlzLnN0cmVhbS5wb2x5Z29uRW5kKCk7IH1cbn07XG5cbmZ1bmN0aW9uIGZpdChwcm9qZWN0aW9uLCBmaXRCb3VuZHMsIG9iamVjdCkge1xuICB2YXIgY2xpcCA9IHByb2plY3Rpb24uY2xpcEV4dGVudCAmJiBwcm9qZWN0aW9uLmNsaXBFeHRlbnQoKTtcbiAgcHJvamVjdGlvbi5zY2FsZSgxNTApLnRyYW5zbGF0ZShbMCwgMF0pO1xuICBpZiAoY2xpcCAhPSBudWxsKSBwcm9qZWN0aW9uLmNsaXBFeHRlbnQobnVsbCk7XG4gIGdlb1N0cmVhbShvYmplY3QsIHByb2plY3Rpb24uc3RyZWFtKGJvdW5kc1N0cmVhbSQxKSk7XG4gIGZpdEJvdW5kcyhib3VuZHNTdHJlYW0kMS5yZXN1bHQoKSk7XG4gIGlmIChjbGlwICE9IG51bGwpIHByb2plY3Rpb24uY2xpcEV4dGVudChjbGlwKTtcbiAgcmV0dXJuIHByb2plY3Rpb247XG59XG5cbmZ1bmN0aW9uIGZpdEV4dGVudChwcm9qZWN0aW9uLCBleHRlbnQsIG9iamVjdCkge1xuICByZXR1cm4gZml0KHByb2plY3Rpb24sIGZ1bmN0aW9uKGIpIHtcbiAgICB2YXIgdyA9IGV4dGVudFsxXVswXSAtIGV4dGVudFswXVswXSxcbiAgICAgICAgaCA9IGV4dGVudFsxXVsxXSAtIGV4dGVudFswXVsxXSxcbiAgICAgICAgayA9IE1hdGgubWluKHcgLyAoYlsxXVswXSAtIGJbMF1bMF0pLCBoIC8gKGJbMV1bMV0gLSBiWzBdWzFdKSksXG4gICAgICAgIHggPSArZXh0ZW50WzBdWzBdICsgKHcgLSBrICogKGJbMV1bMF0gKyBiWzBdWzBdKSkgLyAyLFxuICAgICAgICB5ID0gK2V4dGVudFswXVsxXSArIChoIC0gayAqIChiWzFdWzFdICsgYlswXVsxXSkpIC8gMjtcbiAgICBwcm9qZWN0aW9uLnNjYWxlKDE1MCAqIGspLnRyYW5zbGF0ZShbeCwgeV0pO1xuICB9LCBvYmplY3QpO1xufVxuXG5mdW5jdGlvbiBmaXRTaXplKHByb2plY3Rpb24sIHNpemUsIG9iamVjdCkge1xuICByZXR1cm4gZml0RXh0ZW50KHByb2plY3Rpb24sIFtbMCwgMF0sIHNpemVdLCBvYmplY3QpO1xufVxuXG5mdW5jdGlvbiBmaXRXaWR0aChwcm9qZWN0aW9uLCB3aWR0aCwgb2JqZWN0KSB7XG4gIHJldHVybiBmaXQocHJvamVjdGlvbiwgZnVuY3Rpb24oYikge1xuICAgIHZhciB3ID0gK3dpZHRoLFxuICAgICAgICBrID0gdyAvIChiWzFdWzBdIC0gYlswXVswXSksXG4gICAgICAgIHggPSAodyAtIGsgKiAoYlsxXVswXSArIGJbMF1bMF0pKSAvIDIsXG4gICAgICAgIHkgPSAtayAqIGJbMF1bMV07XG4gICAgcHJvamVjdGlvbi5zY2FsZSgxNTAgKiBrKS50cmFuc2xhdGUoW3gsIHldKTtcbiAgfSwgb2JqZWN0KTtcbn1cblxuZnVuY3Rpb24gZml0SGVpZ2h0KHByb2plY3Rpb24sIGhlaWdodCwgb2JqZWN0KSB7XG4gIHJldHVybiBmaXQocHJvamVjdGlvbiwgZnVuY3Rpb24oYikge1xuICAgIHZhciBoID0gK2hlaWdodCxcbiAgICAgICAgayA9IGggLyAoYlsxXVsxXSAtIGJbMF1bMV0pLFxuICAgICAgICB4ID0gLWsgKiBiWzBdWzBdLFxuICAgICAgICB5ID0gKGggLSBrICogKGJbMV1bMV0gKyBiWzBdWzFdKSkgLyAyO1xuICAgIHByb2plY3Rpb24uc2NhbGUoMTUwICogaykudHJhbnNsYXRlKFt4LCB5XSk7XG4gIH0sIG9iamVjdCk7XG59XG5cbnZhciBtYXhEZXB0aCA9IDE2O1xudmFyIGNvc01pbkRpc3RhbmNlID0gY29zKDMwICogcmFkaWFucyk7IC8vIGNvcyhtaW5pbXVtIGFuZ3VsYXIgZGlzdGFuY2UpXG5cbnZhciByZXNhbXBsZSA9IGZ1bmN0aW9uKHByb2plY3QsIGRlbHRhMikge1xuICByZXR1cm4gK2RlbHRhMiA/IHJlc2FtcGxlJDEocHJvamVjdCwgZGVsdGEyKSA6IHJlc2FtcGxlTm9uZShwcm9qZWN0KTtcbn07XG5cbmZ1bmN0aW9uIHJlc2FtcGxlTm9uZShwcm9qZWN0KSB7XG4gIHJldHVybiB0cmFuc2Zvcm1lcih7XG4gICAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICAgIHggPSBwcm9qZWN0KHgsIHkpO1xuICAgICAgdGhpcy5zdHJlYW0ucG9pbnQoeFswXSwgeFsxXSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVzYW1wbGUkMShwcm9qZWN0LCBkZWx0YTIpIHtcblxuICBmdW5jdGlvbiByZXNhbXBsZUxpbmVUbyh4MCwgeTAsIGxhbWJkYTAsIGEwLCBiMCwgYzAsIHgxLCB5MSwgbGFtYmRhMSwgYTEsIGIxLCBjMSwgZGVwdGgsIHN0cmVhbSkge1xuICAgIHZhciBkeCA9IHgxIC0geDAsXG4gICAgICAgIGR5ID0geTEgLSB5MCxcbiAgICAgICAgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeTtcbiAgICBpZiAoZDIgPiA0ICogZGVsdGEyICYmIGRlcHRoLS0pIHtcbiAgICAgIHZhciBhID0gYTAgKyBhMSxcbiAgICAgICAgICBiID0gYjAgKyBiMSxcbiAgICAgICAgICBjID0gYzAgKyBjMSxcbiAgICAgICAgICBtID0gc3FydChhICogYSArIGIgKiBiICsgYyAqIGMpLFxuICAgICAgICAgIHBoaTIgPSBhc2luKGMgLz0gbSksXG4gICAgICAgICAgbGFtYmRhMiA9IGFicyhhYnMoYykgLSAxKSA8IGVwc2lsb24gfHwgYWJzKGxhbWJkYTAgLSBsYW1iZGExKSA8IGVwc2lsb24gPyAobGFtYmRhMCArIGxhbWJkYTEpIC8gMiA6IGF0YW4yKGIsIGEpLFxuICAgICAgICAgIHAgPSBwcm9qZWN0KGxhbWJkYTIsIHBoaTIpLFxuICAgICAgICAgIHgyID0gcFswXSxcbiAgICAgICAgICB5MiA9IHBbMV0sXG4gICAgICAgICAgZHgyID0geDIgLSB4MCxcbiAgICAgICAgICBkeTIgPSB5MiAtIHkwLFxuICAgICAgICAgIGR6ID0gZHkgKiBkeDIgLSBkeCAqIGR5MjtcbiAgICAgIGlmIChkeiAqIGR6IC8gZDIgPiBkZWx0YTIgLy8gcGVycGVuZGljdWxhciBwcm9qZWN0ZWQgZGlzdGFuY2VcbiAgICAgICAgICB8fCBhYnMoKGR4ICogZHgyICsgZHkgKiBkeTIpIC8gZDIgLSAwLjUpID4gMC4zIC8vIG1pZHBvaW50IGNsb3NlIHRvIGFuIGVuZFxuICAgICAgICAgIHx8IGEwICogYTEgKyBiMCAqIGIxICsgYzAgKiBjMSA8IGNvc01pbkRpc3RhbmNlKSB7IC8vIGFuZ3VsYXIgZGlzdGFuY2VcbiAgICAgICAgcmVzYW1wbGVMaW5lVG8oeDAsIHkwLCBsYW1iZGEwLCBhMCwgYjAsIGMwLCB4MiwgeTIsIGxhbWJkYTIsIGEgLz0gbSwgYiAvPSBtLCBjLCBkZXB0aCwgc3RyZWFtKTtcbiAgICAgICAgc3RyZWFtLnBvaW50KHgyLCB5Mik7XG4gICAgICAgIHJlc2FtcGxlTGluZVRvKHgyLCB5MiwgbGFtYmRhMiwgYSwgYiwgYywgeDEsIHkxLCBsYW1iZGExLCBhMSwgYjEsIGMxLCBkZXB0aCwgc3RyZWFtKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgIHZhciBsYW1iZGEwMCwgeDAwLCB5MDAsIGEwMCwgYjAwLCBjMDAsIC8vIGZpcnN0IHBvaW50XG4gICAgICAgIGxhbWJkYTAsIHgwLCB5MCwgYTAsIGIwLCBjMDsgLy8gcHJldmlvdXMgcG9pbnRcblxuICAgIHZhciByZXNhbXBsZVN0cmVhbSA9IHtcbiAgICAgIHBvaW50OiBwb2ludCxcbiAgICAgIGxpbmVTdGFydDogbGluZVN0YXJ0LFxuICAgICAgbGluZUVuZDogbGluZUVuZCxcbiAgICAgIHBvbHlnb25TdGFydDogZnVuY3Rpb24oKSB7IHN0cmVhbS5wb2x5Z29uU3RhcnQoKTsgcmVzYW1wbGVTdHJlYW0ubGluZVN0YXJ0ID0gcmluZ1N0YXJ0OyB9LFxuICAgICAgcG9seWdvbkVuZDogZnVuY3Rpb24oKSB7IHN0cmVhbS5wb2x5Z29uRW5kKCk7IHJlc2FtcGxlU3RyZWFtLmxpbmVTdGFydCA9IGxpbmVTdGFydDsgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBwb2ludCh4LCB5KSB7XG4gICAgICB4ID0gcHJvamVjdCh4LCB5KTtcbiAgICAgIHN0cmVhbS5wb2ludCh4WzBdLCB4WzFdKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaW5lU3RhcnQoKSB7XG4gICAgICB4MCA9IE5hTjtcbiAgICAgIHJlc2FtcGxlU3RyZWFtLnBvaW50ID0gbGluZVBvaW50O1xuICAgICAgc3RyZWFtLmxpbmVTdGFydCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpbmVQb2ludChsYW1iZGEsIHBoaSkge1xuICAgICAgdmFyIGMgPSBjYXJ0ZXNpYW4oW2xhbWJkYSwgcGhpXSksIHAgPSBwcm9qZWN0KGxhbWJkYSwgcGhpKTtcbiAgICAgIHJlc2FtcGxlTGluZVRvKHgwLCB5MCwgbGFtYmRhMCwgYTAsIGIwLCBjMCwgeDAgPSBwWzBdLCB5MCA9IHBbMV0sIGxhbWJkYTAgPSBsYW1iZGEsIGEwID0gY1swXSwgYjAgPSBjWzFdLCBjMCA9IGNbMl0sIG1heERlcHRoLCBzdHJlYW0pO1xuICAgICAgc3RyZWFtLnBvaW50KHgwLCB5MCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGluZUVuZCgpIHtcbiAgICAgIHJlc2FtcGxlU3RyZWFtLnBvaW50ID0gcG9pbnQ7XG4gICAgICBzdHJlYW0ubGluZUVuZCgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJpbmdTdGFydCgpIHtcbiAgICAgIGxpbmVTdGFydCgpO1xuICAgICAgcmVzYW1wbGVTdHJlYW0ucG9pbnQgPSByaW5nUG9pbnQ7XG4gICAgICByZXNhbXBsZVN0cmVhbS5saW5lRW5kID0gcmluZ0VuZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByaW5nUG9pbnQobGFtYmRhLCBwaGkpIHtcbiAgICAgIGxpbmVQb2ludChsYW1iZGEwMCA9IGxhbWJkYSwgcGhpKSwgeDAwID0geDAsIHkwMCA9IHkwLCBhMDAgPSBhMCwgYjAwID0gYjAsIGMwMCA9IGMwO1xuICAgICAgcmVzYW1wbGVTdHJlYW0ucG9pbnQgPSBsaW5lUG9pbnQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmluZ0VuZCgpIHtcbiAgICAgIHJlc2FtcGxlTGluZVRvKHgwLCB5MCwgbGFtYmRhMCwgYTAsIGIwLCBjMCwgeDAwLCB5MDAsIGxhbWJkYTAwLCBhMDAsIGIwMCwgYzAwLCBtYXhEZXB0aCwgc3RyZWFtKTtcbiAgICAgIHJlc2FtcGxlU3RyZWFtLmxpbmVFbmQgPSBsaW5lRW5kO1xuICAgICAgbGluZUVuZCgpO1xuICAgIH1cblxuICAgIHJldHVybiByZXNhbXBsZVN0cmVhbTtcbiAgfTtcbn1cblxudmFyIHRyYW5zZm9ybVJhZGlhbnMgPSB0cmFuc2Zvcm1lcih7XG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdGhpcy5zdHJlYW0ucG9pbnQoeCAqIHJhZGlhbnMsIHkgKiByYWRpYW5zKTtcbiAgfVxufSk7XG5cbmZ1bmN0aW9uIHRyYW5zZm9ybVJvdGF0ZShyb3RhdGUpIHtcbiAgcmV0dXJuIHRyYW5zZm9ybWVyKHtcbiAgICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgICAgdmFyIHIgPSByb3RhdGUoeCwgeSk7XG4gICAgICByZXR1cm4gdGhpcy5zdHJlYW0ucG9pbnQoclswXSwgclsxXSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gcHJvamVjdGlvbihwcm9qZWN0KSB7XG4gIHJldHVybiBwcm9qZWN0aW9uTXV0YXRvcihmdW5jdGlvbigpIHsgcmV0dXJuIHByb2plY3Q7IH0pKCk7XG59XG5cbmZ1bmN0aW9uIHByb2plY3Rpb25NdXRhdG9yKHByb2plY3RBdCkge1xuICB2YXIgcHJvamVjdCxcbiAgICAgIGsgPSAxNTAsIC8vIHNjYWxlXG4gICAgICB4ID0gNDgwLCB5ID0gMjUwLCAvLyB0cmFuc2xhdGVcbiAgICAgIGR4LCBkeSwgbGFtYmRhID0gMCwgcGhpID0gMCwgLy8gY2VudGVyXG4gICAgICBkZWx0YUxhbWJkYSA9IDAsIGRlbHRhUGhpID0gMCwgZGVsdGFHYW1tYSA9IDAsIHJvdGF0ZSwgcHJvamVjdFJvdGF0ZSwgLy8gcm90YXRlXG4gICAgICB0aGV0YSA9IG51bGwsIHByZWNsaXAgPSBjbGlwQW50aW1lcmlkaWFuLCAvLyBjbGlwIGFuZ2xlXG4gICAgICB4MCA9IG51bGwsIHkwLCB4MSwgeTEsIHBvc3RjbGlwID0gaWRlbnRpdHksIC8vIGNsaXAgZXh0ZW50XG4gICAgICBkZWx0YTIgPSAwLjUsIHByb2plY3RSZXNhbXBsZSA9IHJlc2FtcGxlKHByb2plY3RUcmFuc2Zvcm0sIGRlbHRhMiksIC8vIHByZWNpc2lvblxuICAgICAgY2FjaGUsXG4gICAgICBjYWNoZVN0cmVhbTtcblxuICBmdW5jdGlvbiBwcm9qZWN0aW9uKHBvaW50KSB7XG4gICAgcG9pbnQgPSBwcm9qZWN0Um90YXRlKHBvaW50WzBdICogcmFkaWFucywgcG9pbnRbMV0gKiByYWRpYW5zKTtcbiAgICByZXR1cm4gW3BvaW50WzBdICogayArIGR4LCBkeSAtIHBvaW50WzFdICoga107XG4gIH1cblxuICBmdW5jdGlvbiBpbnZlcnQocG9pbnQpIHtcbiAgICBwb2ludCA9IHByb2plY3RSb3RhdGUuaW52ZXJ0KChwb2ludFswXSAtIGR4KSAvIGssIChkeSAtIHBvaW50WzFdKSAvIGspO1xuICAgIHJldHVybiBwb2ludCAmJiBbcG9pbnRbMF0gKiBkZWdyZWVzLCBwb2ludFsxXSAqIGRlZ3JlZXNdO1xuICB9XG5cbiAgZnVuY3Rpb24gcHJvamVjdFRyYW5zZm9ybSh4LCB5KSB7XG4gICAgcmV0dXJuIHggPSBwcm9qZWN0KHgsIHkpLCBbeFswXSAqIGsgKyBkeCwgZHkgLSB4WzFdICoga107XG4gIH1cblxuICBwcm9qZWN0aW9uLnN0cmVhbSA9IGZ1bmN0aW9uKHN0cmVhbSkge1xuICAgIHJldHVybiBjYWNoZSAmJiBjYWNoZVN0cmVhbSA9PT0gc3RyZWFtID8gY2FjaGUgOiBjYWNoZSA9IHRyYW5zZm9ybVJhZGlhbnModHJhbnNmb3JtUm90YXRlKHJvdGF0ZSkocHJlY2xpcChwcm9qZWN0UmVzYW1wbGUocG9zdGNsaXAoY2FjaGVTdHJlYW0gPSBzdHJlYW0pKSkpKTtcbiAgfTtcblxuICBwcm9qZWN0aW9uLnByZWNsaXAgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocHJlY2xpcCA9IF8sIHRoZXRhID0gdW5kZWZpbmVkLCByZXNldCgpKSA6IHByZWNsaXA7XG4gIH07XG5cbiAgcHJvamVjdGlvbi5wb3N0Y2xpcCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwb3N0Y2xpcCA9IF8sIHgwID0geTAgPSB4MSA9IHkxID0gbnVsbCwgcmVzZXQoKSkgOiBwb3N0Y2xpcDtcbiAgfTtcblxuICBwcm9qZWN0aW9uLmNsaXBBbmdsZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwcmVjbGlwID0gK18gPyBjbGlwQ2lyY2xlKHRoZXRhID0gXyAqIHJhZGlhbnMpIDogKHRoZXRhID0gbnVsbCwgY2xpcEFudGltZXJpZGlhbiksIHJlc2V0KCkpIDogdGhldGEgKiBkZWdyZWVzO1xuICB9O1xuXG4gIHByb2plY3Rpb24uY2xpcEV4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwb3N0Y2xpcCA9IF8gPT0gbnVsbCA/ICh4MCA9IHkwID0geDEgPSB5MSA9IG51bGwsIGlkZW50aXR5KSA6IGNsaXBSZWN0YW5nbGUoeDAgPSArX1swXVswXSwgeTAgPSArX1swXVsxXSwgeDEgPSArX1sxXVswXSwgeTEgPSArX1sxXVsxXSksIHJlc2V0KCkpIDogeDAgPT0gbnVsbCA/IG51bGwgOiBbW3gwLCB5MF0sIFt4MSwgeTFdXTtcbiAgfTtcblxuICBwcm9qZWN0aW9uLnNjYWxlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGsgPSArXywgcmVjZW50ZXIoKSkgOiBrO1xuICB9O1xuXG4gIHByb2plY3Rpb24udHJhbnNsYXRlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHggPSArX1swXSwgeSA9ICtfWzFdLCByZWNlbnRlcigpKSA6IFt4LCB5XTtcbiAgfTtcblxuICBwcm9qZWN0aW9uLmNlbnRlciA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChsYW1iZGEgPSBfWzBdICUgMzYwICogcmFkaWFucywgcGhpID0gX1sxXSAlIDM2MCAqIHJhZGlhbnMsIHJlY2VudGVyKCkpIDogW2xhbWJkYSAqIGRlZ3JlZXMsIHBoaSAqIGRlZ3JlZXNdO1xuICB9O1xuXG4gIHByb2plY3Rpb24ucm90YXRlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRlbHRhTGFtYmRhID0gX1swXSAlIDM2MCAqIHJhZGlhbnMsIGRlbHRhUGhpID0gX1sxXSAlIDM2MCAqIHJhZGlhbnMsIGRlbHRhR2FtbWEgPSBfLmxlbmd0aCA+IDIgPyBfWzJdICUgMzYwICogcmFkaWFucyA6IDAsIHJlY2VudGVyKCkpIDogW2RlbHRhTGFtYmRhICogZGVncmVlcywgZGVsdGFQaGkgKiBkZWdyZWVzLCBkZWx0YUdhbW1hICogZGVncmVlc107XG4gIH07XG5cbiAgcHJvamVjdGlvbi5wcmVjaXNpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocHJvamVjdFJlc2FtcGxlID0gcmVzYW1wbGUocHJvamVjdFRyYW5zZm9ybSwgZGVsdGEyID0gXyAqIF8pLCByZXNldCgpKSA6IHNxcnQoZGVsdGEyKTtcbiAgfTtcblxuICBwcm9qZWN0aW9uLmZpdEV4dGVudCA9IGZ1bmN0aW9uKGV4dGVudCwgb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZpdEV4dGVudChwcm9qZWN0aW9uLCBleHRlbnQsIG9iamVjdCk7XG4gIH07XG5cbiAgcHJvamVjdGlvbi5maXRTaXplID0gZnVuY3Rpb24oc2l6ZSwgb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZpdFNpemUocHJvamVjdGlvbiwgc2l6ZSwgb2JqZWN0KTtcbiAgfTtcblxuICBwcm9qZWN0aW9uLmZpdFdpZHRoID0gZnVuY3Rpb24od2lkdGgsIG9iamVjdCkge1xuICAgIHJldHVybiBmaXRXaWR0aChwcm9qZWN0aW9uLCB3aWR0aCwgb2JqZWN0KTtcbiAgfTtcblxuICBwcm9qZWN0aW9uLmZpdEhlaWdodCA9IGZ1bmN0aW9uKGhlaWdodCwgb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZpdEhlaWdodChwcm9qZWN0aW9uLCBoZWlnaHQsIG9iamVjdCk7XG4gIH07XG5cbiAgZnVuY3Rpb24gcmVjZW50ZXIoKSB7XG4gICAgcHJvamVjdFJvdGF0ZSA9IGNvbXBvc2Uocm90YXRlID0gcm90YXRlUmFkaWFucyhkZWx0YUxhbWJkYSwgZGVsdGFQaGksIGRlbHRhR2FtbWEpLCBwcm9qZWN0KTtcbiAgICB2YXIgY2VudGVyID0gcHJvamVjdChsYW1iZGEsIHBoaSk7XG4gICAgZHggPSB4IC0gY2VudGVyWzBdICogaztcbiAgICBkeSA9IHkgKyBjZW50ZXJbMV0gKiBrO1xuICAgIHJldHVybiByZXNldCgpO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgY2FjaGUgPSBjYWNoZVN0cmVhbSA9IG51bGw7XG4gICAgcmV0dXJuIHByb2plY3Rpb247XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcHJvamVjdCA9IHByb2plY3RBdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIHByb2plY3Rpb24uaW52ZXJ0ID0gcHJvamVjdC5pbnZlcnQgJiYgaW52ZXJ0O1xuICAgIHJldHVybiByZWNlbnRlcigpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBjb25pY1Byb2plY3Rpb24ocHJvamVjdEF0KSB7XG4gIHZhciBwaGkwID0gMCxcbiAgICAgIHBoaTEgPSBwaSAvIDMsXG4gICAgICBtID0gcHJvamVjdGlvbk11dGF0b3IocHJvamVjdEF0KSxcbiAgICAgIHAgPSBtKHBoaTAsIHBoaTEpO1xuXG4gIHAucGFyYWxsZWxzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gbShwaGkwID0gX1swXSAqIHJhZGlhbnMsIHBoaTEgPSBfWzFdICogcmFkaWFucykgOiBbcGhpMCAqIGRlZ3JlZXMsIHBoaTEgKiBkZWdyZWVzXTtcbiAgfTtcblxuICByZXR1cm4gcDtcbn1cblxuZnVuY3Rpb24gY3lsaW5kcmljYWxFcXVhbEFyZWFSYXcocGhpMCkge1xuICB2YXIgY29zUGhpMCA9IGNvcyhwaGkwKTtcblxuICBmdW5jdGlvbiBmb3J3YXJkKGxhbWJkYSwgcGhpKSB7XG4gICAgcmV0dXJuIFtsYW1iZGEgKiBjb3NQaGkwLCBzaW4ocGhpKSAvIGNvc1BoaTBdO1xuICB9XG5cbiAgZm9yd2FyZC5pbnZlcnQgPSBmdW5jdGlvbih4LCB5KSB7XG4gICAgcmV0dXJuIFt4IC8gY29zUGhpMCwgYXNpbih5ICogY29zUGhpMCldO1xuICB9O1xuXG4gIHJldHVybiBmb3J3YXJkO1xufVxuXG5mdW5jdGlvbiBjb25pY0VxdWFsQXJlYVJhdyh5MCwgeTEpIHtcbiAgdmFyIHN5MCA9IHNpbih5MCksIG4gPSAoc3kwICsgc2luKHkxKSkgLyAyO1xuXG4gIC8vIEFyZSB0aGUgcGFyYWxsZWxzIHN5bW1ldHJpY2FsIGFyb3VuZCB0aGUgRXF1YXRvcj9cbiAgaWYgKGFicyhuKSA8IGVwc2lsb24pIHJldHVybiBjeWxpbmRyaWNhbEVxdWFsQXJlYVJhdyh5MCk7XG5cbiAgdmFyIGMgPSAxICsgc3kwICogKDIgKiBuIC0gc3kwKSwgcjAgPSBzcXJ0KGMpIC8gbjtcblxuICBmdW5jdGlvbiBwcm9qZWN0KHgsIHkpIHtcbiAgICB2YXIgciA9IHNxcnQoYyAtIDIgKiBuICogc2luKHkpKSAvIG47XG4gICAgcmV0dXJuIFtyICogc2luKHggKj0gbiksIHIwIC0gciAqIGNvcyh4KV07XG4gIH1cblxuICBwcm9qZWN0LmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB2YXIgcjB5ID0gcjAgLSB5O1xuICAgIHJldHVybiBbYXRhbjIoeCwgYWJzKHIweSkpIC8gbiAqIHNpZ24ocjB5KSwgYXNpbigoYyAtICh4ICogeCArIHIweSAqIHIweSkgKiBuICogbikgLyAoMiAqIG4pKV07XG4gIH07XG5cbiAgcmV0dXJuIHByb2plY3Q7XG59XG5cbnZhciBjb25pY0VxdWFsQXJlYSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gY29uaWNQcm9qZWN0aW9uKGNvbmljRXF1YWxBcmVhUmF3KVxuICAgICAgLnNjYWxlKDE1NS40MjQpXG4gICAgICAuY2VudGVyKFswLCAzMy42NDQyXSk7XG59O1xuXG52YXIgYWxiZXJzID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBjb25pY0VxdWFsQXJlYSgpXG4gICAgICAucGFyYWxsZWxzKFsyOS41LCA0NS41XSlcbiAgICAgIC5zY2FsZSgxMDcwKVxuICAgICAgLnRyYW5zbGF0ZShbNDgwLCAyNTBdKVxuICAgICAgLnJvdGF0ZShbOTYsIDBdKVxuICAgICAgLmNlbnRlcihbLTAuNiwgMzguN10pO1xufTtcblxuLy8gVGhlIHByb2plY3Rpb25zIG11c3QgaGF2ZSBtdXR1YWxseSBleGNsdXNpdmUgY2xpcCByZWdpb25zIG9uIHRoZSBzcGhlcmUsXG4vLyBhcyB0aGlzIHdpbGwgYXZvaWQgZW1pdHRpbmcgaW50ZXJsZWF2aW5nIGxpbmVzIGFuZCBwb2x5Z29ucy5cbmZ1bmN0aW9uIG11bHRpcGxleChzdHJlYW1zKSB7XG4gIHZhciBuID0gc3RyZWFtcy5sZW5ndGg7XG4gIHJldHVybiB7XG4gICAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHsgdmFyIGkgPSAtMTsgd2hpbGUgKCsraSA8IG4pIHN0cmVhbXNbaV0ucG9pbnQoeCwgeSk7IH0sXG4gICAgc3BoZXJlOiBmdW5jdGlvbigpIHsgdmFyIGkgPSAtMTsgd2hpbGUgKCsraSA8IG4pIHN0cmVhbXNbaV0uc3BoZXJlKCk7IH0sXG4gICAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHsgdmFyIGkgPSAtMTsgd2hpbGUgKCsraSA8IG4pIHN0cmVhbXNbaV0ubGluZVN0YXJ0KCk7IH0sXG4gICAgbGluZUVuZDogZnVuY3Rpb24oKSB7IHZhciBpID0gLTE7IHdoaWxlICgrK2kgPCBuKSBzdHJlYW1zW2ldLmxpbmVFbmQoKTsgfSxcbiAgICBwb2x5Z29uU3RhcnQ6IGZ1bmN0aW9uKCkgeyB2YXIgaSA9IC0xOyB3aGlsZSAoKytpIDwgbikgc3RyZWFtc1tpXS5wb2x5Z29uU3RhcnQoKTsgfSxcbiAgICBwb2x5Z29uRW5kOiBmdW5jdGlvbigpIHsgdmFyIGkgPSAtMTsgd2hpbGUgKCsraSA8IG4pIHN0cmVhbXNbaV0ucG9seWdvbkVuZCgpOyB9XG4gIH07XG59XG5cbi8vIEEgY29tcG9zaXRlIHByb2plY3Rpb24gZm9yIHRoZSBVbml0ZWQgU3RhdGVzLCBjb25maWd1cmVkIGJ5IGRlZmF1bHQgZm9yXG4vLyA5NjDDlzUwMC4gVGhlIHByb2plY3Rpb24gYWxzbyB3b3JrcyBxdWl0ZSB3ZWxsIGF0IDk2MMOXNjAwIGlmIHlvdSBjaGFuZ2UgdGhlXG4vLyBzY2FsZSB0byAxMjg1IGFuZCBhZGp1c3QgdGhlIHRyYW5zbGF0ZSBhY2NvcmRpbmdseS4gVGhlIHNldCBvZiBzdGFuZGFyZFxuLy8gcGFyYWxsZWxzIGZvciBlYWNoIHJlZ2lvbiBjb21lcyBmcm9tIFVTR1MsIHdoaWNoIGlzIHB1Ymxpc2hlZCBoZXJlOlxuLy8gaHR0cDovL2Vnc2MudXNncy5nb3YvaXNiL3B1YnMvTWFwUHJvamVjdGlvbnMvcHJvamVjdGlvbnMuaHRtbCNhbGJlcnNcbnZhciBhbGJlcnNVc2EgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGNhY2hlLFxuICAgICAgY2FjaGVTdHJlYW0sXG4gICAgICBsb3dlcjQ4ID0gYWxiZXJzKCksIGxvd2VyNDhQb2ludCxcbiAgICAgIGFsYXNrYSA9IGNvbmljRXF1YWxBcmVhKCkucm90YXRlKFsxNTQsIDBdKS5jZW50ZXIoWy0yLCA1OC41XSkucGFyYWxsZWxzKFs1NSwgNjVdKSwgYWxhc2thUG9pbnQsIC8vIEVQU0c6MzMzOFxuICAgICAgaGF3YWlpID0gY29uaWNFcXVhbEFyZWEoKS5yb3RhdGUoWzE1NywgMF0pLmNlbnRlcihbLTMsIDE5LjldKS5wYXJhbGxlbHMoWzgsIDE4XSksIGhhd2FpaVBvaW50LCAvLyBFU1JJOjEwMjAwN1xuICAgICAgcG9pbnQsIHBvaW50U3RyZWFtID0ge3BvaW50OiBmdW5jdGlvbih4LCB5KSB7IHBvaW50ID0gW3gsIHldOyB9fTtcblxuICBmdW5jdGlvbiBhbGJlcnNVc2EoY29vcmRpbmF0ZXMpIHtcbiAgICB2YXIgeCA9IGNvb3JkaW5hdGVzWzBdLCB5ID0gY29vcmRpbmF0ZXNbMV07XG4gICAgcmV0dXJuIHBvaW50ID0gbnVsbCwgKGxvd2VyNDhQb2ludC5wb2ludCh4LCB5KSwgcG9pbnQpXG4gICAgICAgIHx8IChhbGFza2FQb2ludC5wb2ludCh4LCB5KSwgcG9pbnQpXG4gICAgICAgIHx8IChoYXdhaWlQb2ludC5wb2ludCh4LCB5KSwgcG9pbnQpO1xuICB9XG5cbiAgYWxiZXJzVXNhLmludmVydCA9IGZ1bmN0aW9uKGNvb3JkaW5hdGVzKSB7XG4gICAgdmFyIGsgPSBsb3dlcjQ4LnNjYWxlKCksXG4gICAgICAgIHQgPSBsb3dlcjQ4LnRyYW5zbGF0ZSgpLFxuICAgICAgICB4ID0gKGNvb3JkaW5hdGVzWzBdIC0gdFswXSkgLyBrLFxuICAgICAgICB5ID0gKGNvb3JkaW5hdGVzWzFdIC0gdFsxXSkgLyBrO1xuICAgIHJldHVybiAoeSA+PSAwLjEyMCAmJiB5IDwgMC4yMzQgJiYgeCA+PSAtMC40MjUgJiYgeCA8IC0wLjIxNCA/IGFsYXNrYVxuICAgICAgICA6IHkgPj0gMC4xNjYgJiYgeSA8IDAuMjM0ICYmIHggPj0gLTAuMjE0ICYmIHggPCAtMC4xMTUgPyBoYXdhaWlcbiAgICAgICAgOiBsb3dlcjQ4KS5pbnZlcnQoY29vcmRpbmF0ZXMpO1xuICB9O1xuXG4gIGFsYmVyc1VzYS5zdHJlYW0gPSBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICByZXR1cm4gY2FjaGUgJiYgY2FjaGVTdHJlYW0gPT09IHN0cmVhbSA/IGNhY2hlIDogY2FjaGUgPSBtdWx0aXBsZXgoW2xvd2VyNDguc3RyZWFtKGNhY2hlU3RyZWFtID0gc3RyZWFtKSwgYWxhc2thLnN0cmVhbShzdHJlYW0pLCBoYXdhaWkuc3RyZWFtKHN0cmVhbSldKTtcbiAgfTtcblxuICBhbGJlcnNVc2EucHJlY2lzaW9uID0gZnVuY3Rpb24oXykge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGxvd2VyNDgucHJlY2lzaW9uKCk7XG4gICAgbG93ZXI0OC5wcmVjaXNpb24oXyksIGFsYXNrYS5wcmVjaXNpb24oXyksIGhhd2FpaS5wcmVjaXNpb24oXyk7XG4gICAgcmV0dXJuIHJlc2V0KCk7XG4gIH07XG5cbiAgYWxiZXJzVXNhLnNjYWxlID0gZnVuY3Rpb24oXykge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGxvd2VyNDguc2NhbGUoKTtcbiAgICBsb3dlcjQ4LnNjYWxlKF8pLCBhbGFza2Euc2NhbGUoXyAqIDAuMzUpLCBoYXdhaWkuc2NhbGUoXyk7XG4gICAgcmV0dXJuIGFsYmVyc1VzYS50cmFuc2xhdGUobG93ZXI0OC50cmFuc2xhdGUoKSk7XG4gIH07XG5cbiAgYWxiZXJzVXNhLnRyYW5zbGF0ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBsb3dlcjQ4LnRyYW5zbGF0ZSgpO1xuICAgIHZhciBrID0gbG93ZXI0OC5zY2FsZSgpLCB4ID0gK19bMF0sIHkgPSArX1sxXTtcblxuICAgIGxvd2VyNDhQb2ludCA9IGxvd2VyNDhcbiAgICAgICAgLnRyYW5zbGF0ZShfKVxuICAgICAgICAuY2xpcEV4dGVudChbW3ggLSAwLjQ1NSAqIGssIHkgLSAwLjIzOCAqIGtdLCBbeCArIDAuNDU1ICogaywgeSArIDAuMjM4ICoga11dKVxuICAgICAgICAuc3RyZWFtKHBvaW50U3RyZWFtKTtcblxuICAgIGFsYXNrYVBvaW50ID0gYWxhc2thXG4gICAgICAgIC50cmFuc2xhdGUoW3ggLSAwLjMwNyAqIGssIHkgKyAwLjIwMSAqIGtdKVxuICAgICAgICAuY2xpcEV4dGVudChbW3ggLSAwLjQyNSAqIGsgKyBlcHNpbG9uLCB5ICsgMC4xMjAgKiBrICsgZXBzaWxvbl0sIFt4IC0gMC4yMTQgKiBrIC0gZXBzaWxvbiwgeSArIDAuMjM0ICogayAtIGVwc2lsb25dXSlcbiAgICAgICAgLnN0cmVhbShwb2ludFN0cmVhbSk7XG5cbiAgICBoYXdhaWlQb2ludCA9IGhhd2FpaVxuICAgICAgICAudHJhbnNsYXRlKFt4IC0gMC4yMDUgKiBrLCB5ICsgMC4yMTIgKiBrXSlcbiAgICAgICAgLmNsaXBFeHRlbnQoW1t4IC0gMC4yMTQgKiBrICsgZXBzaWxvbiwgeSArIDAuMTY2ICogayArIGVwc2lsb25dLCBbeCAtIDAuMTE1ICogayAtIGVwc2lsb24sIHkgKyAwLjIzNCAqIGsgLSBlcHNpbG9uXV0pXG4gICAgICAgIC5zdHJlYW0ocG9pbnRTdHJlYW0pO1xuXG4gICAgcmV0dXJuIHJlc2V0KCk7XG4gIH07XG5cbiAgYWxiZXJzVXNhLmZpdEV4dGVudCA9IGZ1bmN0aW9uKGV4dGVudCwgb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZpdEV4dGVudChhbGJlcnNVc2EsIGV4dGVudCwgb2JqZWN0KTtcbiAgfTtcblxuICBhbGJlcnNVc2EuZml0U2l6ZSA9IGZ1bmN0aW9uKHNpemUsIG9iamVjdCkge1xuICAgIHJldHVybiBmaXRTaXplKGFsYmVyc1VzYSwgc2l6ZSwgb2JqZWN0KTtcbiAgfTtcblxuICBhbGJlcnNVc2EuZml0V2lkdGggPSBmdW5jdGlvbih3aWR0aCwgb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZpdFdpZHRoKGFsYmVyc1VzYSwgd2lkdGgsIG9iamVjdCk7XG4gIH07XG5cbiAgYWxiZXJzVXNhLmZpdEhlaWdodCA9IGZ1bmN0aW9uKGhlaWdodCwgb2JqZWN0KSB7XG4gICAgcmV0dXJuIGZpdEhlaWdodChhbGJlcnNVc2EsIGhlaWdodCwgb2JqZWN0KTtcbiAgfTtcblxuICBmdW5jdGlvbiByZXNldCgpIHtcbiAgICBjYWNoZSA9IGNhY2hlU3RyZWFtID0gbnVsbDtcbiAgICByZXR1cm4gYWxiZXJzVXNhO1xuICB9XG5cbiAgcmV0dXJuIGFsYmVyc1VzYS5zY2FsZSgxMDcwKTtcbn07XG5cbmZ1bmN0aW9uIGF6aW11dGhhbFJhdyhzY2FsZSkge1xuICByZXR1cm4gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciBjeCA9IGNvcyh4KSxcbiAgICAgICAgY3kgPSBjb3MoeSksXG4gICAgICAgIGsgPSBzY2FsZShjeCAqIGN5KTtcbiAgICByZXR1cm4gW1xuICAgICAgayAqIGN5ICogc2luKHgpLFxuICAgICAgayAqIHNpbih5KVxuICAgIF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXppbXV0aGFsSW52ZXJ0KGFuZ2xlKSB7XG4gIHJldHVybiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIHogPSBzcXJ0KHggKiB4ICsgeSAqIHkpLFxuICAgICAgICBjID0gYW5nbGUoeiksXG4gICAgICAgIHNjID0gc2luKGMpLFxuICAgICAgICBjYyA9IGNvcyhjKTtcbiAgICByZXR1cm4gW1xuICAgICAgYXRhbjIoeCAqIHNjLCB6ICogY2MpLFxuICAgICAgYXNpbih6ICYmIHkgKiBzYyAvIHopXG4gICAgXTtcbiAgfVxufVxuXG52YXIgYXppbXV0aGFsRXF1YWxBcmVhUmF3ID0gYXppbXV0aGFsUmF3KGZ1bmN0aW9uKGN4Y3kpIHtcbiAgcmV0dXJuIHNxcnQoMiAvICgxICsgY3hjeSkpO1xufSk7XG5cbmF6aW11dGhhbEVxdWFsQXJlYVJhdy5pbnZlcnQgPSBhemltdXRoYWxJbnZlcnQoZnVuY3Rpb24oeikge1xuICByZXR1cm4gMiAqIGFzaW4oeiAvIDIpO1xufSk7XG5cbnZhciBhemltdXRoYWxFcXVhbEFyZWEgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHByb2plY3Rpb24oYXppbXV0aGFsRXF1YWxBcmVhUmF3KVxuICAgICAgLnNjYWxlKDEyNC43NSlcbiAgICAgIC5jbGlwQW5nbGUoMTgwIC0gMWUtMyk7XG59O1xuXG52YXIgYXppbXV0aGFsRXF1aWRpc3RhbnRSYXcgPSBhemltdXRoYWxSYXcoZnVuY3Rpb24oYykge1xuICByZXR1cm4gKGMgPSBhY29zKGMpKSAmJiBjIC8gc2luKGMpO1xufSk7XG5cbmF6aW11dGhhbEVxdWlkaXN0YW50UmF3LmludmVydCA9IGF6aW11dGhhbEludmVydChmdW5jdGlvbih6KSB7XG4gIHJldHVybiB6O1xufSk7XG5cbnZhciBhemltdXRoYWxFcXVpZGlzdGFudCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gcHJvamVjdGlvbihhemltdXRoYWxFcXVpZGlzdGFudFJhdylcbiAgICAgIC5zY2FsZSg3OS40MTg4KVxuICAgICAgLmNsaXBBbmdsZSgxODAgLSAxZS0zKTtcbn07XG5cbmZ1bmN0aW9uIG1lcmNhdG9yUmF3KGxhbWJkYSwgcGhpKSB7XG4gIHJldHVybiBbbGFtYmRhLCBsb2codGFuKChoYWxmUGkgKyBwaGkpIC8gMikpXTtcbn1cblxubWVyY2F0b3JSYXcuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICByZXR1cm4gW3gsIDIgKiBhdGFuKGV4cCh5KSkgLSBoYWxmUGldO1xufTtcblxudmFyIG1lcmNhdG9yID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBtZXJjYXRvclByb2plY3Rpb24obWVyY2F0b3JSYXcpXG4gICAgICAuc2NhbGUoOTYxIC8gdGF1KTtcbn07XG5cbmZ1bmN0aW9uIG1lcmNhdG9yUHJvamVjdGlvbihwcm9qZWN0KSB7XG4gIHZhciBtID0gcHJvamVjdGlvbihwcm9qZWN0KSxcbiAgICAgIGNlbnRlciA9IG0uY2VudGVyLFxuICAgICAgc2NhbGUgPSBtLnNjYWxlLFxuICAgICAgdHJhbnNsYXRlID0gbS50cmFuc2xhdGUsXG4gICAgICBjbGlwRXh0ZW50ID0gbS5jbGlwRXh0ZW50LFxuICAgICAgeDAgPSBudWxsLCB5MCwgeDEsIHkxOyAvLyBjbGlwIGV4dGVudFxuXG4gIG0uc2NhbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2NhbGUoXyksIHJlY2xpcCgpKSA6IHNjYWxlKCk7XG4gIH07XG5cbiAgbS50cmFuc2xhdGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNsYXRlKF8pLCByZWNsaXAoKSkgOiB0cmFuc2xhdGUoKTtcbiAgfTtcblxuICBtLmNlbnRlciA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjZW50ZXIoXyksIHJlY2xpcCgpKSA6IGNlbnRlcigpO1xuICB9O1xuXG4gIG0uY2xpcEV4dGVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChfID09IG51bGwgPyB4MCA9IHkwID0geDEgPSB5MSA9IG51bGwgOiAoeDAgPSArX1swXVswXSwgeTAgPSArX1swXVsxXSwgeDEgPSArX1sxXVswXSwgeTEgPSArX1sxXVsxXSksIHJlY2xpcCgpKSA6IHgwID09IG51bGwgPyBudWxsIDogW1t4MCwgeTBdLCBbeDEsIHkxXV07XG4gIH07XG5cbiAgZnVuY3Rpb24gcmVjbGlwKCkge1xuICAgIHZhciBrID0gcGkgKiBzY2FsZSgpLFxuICAgICAgICB0ID0gbShyb3RhdGlvbihtLnJvdGF0ZSgpKS5pbnZlcnQoWzAsIDBdKSk7XG4gICAgcmV0dXJuIGNsaXBFeHRlbnQoeDAgPT0gbnVsbFxuICAgICAgICA/IFtbdFswXSAtIGssIHRbMV0gLSBrXSwgW3RbMF0gKyBrLCB0WzFdICsga11dIDogcHJvamVjdCA9PT0gbWVyY2F0b3JSYXdcbiAgICAgICAgPyBbW01hdGgubWF4KHRbMF0gLSBrLCB4MCksIHkwXSwgW01hdGgubWluKHRbMF0gKyBrLCB4MSksIHkxXV1cbiAgICAgICAgOiBbW3gwLCBNYXRoLm1heCh0WzFdIC0gaywgeTApXSwgW3gxLCBNYXRoLm1pbih0WzFdICsgaywgeTEpXV0pO1xuICB9XG5cbiAgcmV0dXJuIHJlY2xpcCgpO1xufVxuXG5mdW5jdGlvbiB0YW55KHkpIHtcbiAgcmV0dXJuIHRhbigoaGFsZlBpICsgeSkgLyAyKTtcbn1cblxuZnVuY3Rpb24gY29uaWNDb25mb3JtYWxSYXcoeTAsIHkxKSB7XG4gIHZhciBjeTAgPSBjb3MoeTApLFxuICAgICAgbiA9IHkwID09PSB5MSA/IHNpbih5MCkgOiBsb2coY3kwIC8gY29zKHkxKSkgLyBsb2codGFueSh5MSkgLyB0YW55KHkwKSksXG4gICAgICBmID0gY3kwICogcG93KHRhbnkoeTApLCBuKSAvIG47XG5cbiAgaWYgKCFuKSByZXR1cm4gbWVyY2F0b3JSYXc7XG5cbiAgZnVuY3Rpb24gcHJvamVjdCh4LCB5KSB7XG4gICAgaWYgKGYgPiAwKSB7IGlmICh5IDwgLWhhbGZQaSArIGVwc2lsb24pIHkgPSAtaGFsZlBpICsgZXBzaWxvbjsgfVxuICAgIGVsc2UgeyBpZiAoeSA+IGhhbGZQaSAtIGVwc2lsb24pIHkgPSBoYWxmUGkgLSBlcHNpbG9uOyB9XG4gICAgdmFyIHIgPSBmIC8gcG93KHRhbnkoeSksIG4pO1xuICAgIHJldHVybiBbciAqIHNpbihuICogeCksIGYgLSByICogY29zKG4gKiB4KV07XG4gIH1cblxuICBwcm9qZWN0LmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB2YXIgZnkgPSBmIC0geSwgciA9IHNpZ24obikgKiBzcXJ0KHggKiB4ICsgZnkgKiBmeSk7XG4gICAgcmV0dXJuIFthdGFuMih4LCBhYnMoZnkpKSAvIG4gKiBzaWduKGZ5KSwgMiAqIGF0YW4ocG93KGYgLyByLCAxIC8gbikpIC0gaGFsZlBpXTtcbiAgfTtcblxuICByZXR1cm4gcHJvamVjdDtcbn1cblxudmFyIGNvbmljQ29uZm9ybWFsID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBjb25pY1Byb2plY3Rpb24oY29uaWNDb25mb3JtYWxSYXcpXG4gICAgICAuc2NhbGUoMTA5LjUpXG4gICAgICAucGFyYWxsZWxzKFszMCwgMzBdKTtcbn07XG5cbmZ1bmN0aW9uIGVxdWlyZWN0YW5ndWxhclJhdyhsYW1iZGEsIHBoaSkge1xuICByZXR1cm4gW2xhbWJkYSwgcGhpXTtcbn1cblxuZXF1aXJlY3Rhbmd1bGFyUmF3LmludmVydCA9IGVxdWlyZWN0YW5ndWxhclJhdztcblxudmFyIGVxdWlyZWN0YW5ndWxhciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gcHJvamVjdGlvbihlcXVpcmVjdGFuZ3VsYXJSYXcpXG4gICAgICAuc2NhbGUoMTUyLjYzKTtcbn07XG5cbmZ1bmN0aW9uIGNvbmljRXF1aWRpc3RhbnRSYXcoeTAsIHkxKSB7XG4gIHZhciBjeTAgPSBjb3MoeTApLFxuICAgICAgbiA9IHkwID09PSB5MSA/IHNpbih5MCkgOiAoY3kwIC0gY29zKHkxKSkgLyAoeTEgLSB5MCksXG4gICAgICBnID0gY3kwIC8gbiArIHkwO1xuXG4gIGlmIChhYnMobikgPCBlcHNpbG9uKSByZXR1cm4gZXF1aXJlY3Rhbmd1bGFyUmF3O1xuXG4gIGZ1bmN0aW9uIHByb2plY3QoeCwgeSkge1xuICAgIHZhciBneSA9IGcgLSB5LCBueCA9IG4gKiB4O1xuICAgIHJldHVybiBbZ3kgKiBzaW4obngpLCBnIC0gZ3kgKiBjb3MobngpXTtcbiAgfVxuXG4gIHByb2plY3QuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICAgIHZhciBneSA9IGcgLSB5O1xuICAgIHJldHVybiBbYXRhbjIoeCwgYWJzKGd5KSkgLyBuICogc2lnbihneSksIGcgLSBzaWduKG4pICogc3FydCh4ICogeCArIGd5ICogZ3kpXTtcbiAgfTtcblxuICByZXR1cm4gcHJvamVjdDtcbn1cblxudmFyIGNvbmljRXF1aWRpc3RhbnQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIGNvbmljUHJvamVjdGlvbihjb25pY0VxdWlkaXN0YW50UmF3KVxuICAgICAgLnNjYWxlKDEzMS4xNTQpXG4gICAgICAuY2VudGVyKFswLCAxMy45Mzg5XSk7XG59O1xuXG5mdW5jdGlvbiBnbm9tb25pY1Jhdyh4LCB5KSB7XG4gIHZhciBjeSA9IGNvcyh5KSwgayA9IGNvcyh4KSAqIGN5O1xuICByZXR1cm4gW2N5ICogc2luKHgpIC8gaywgc2luKHkpIC8ga107XG59XG5cbmdub21vbmljUmF3LmludmVydCA9IGF6aW11dGhhbEludmVydChhdGFuKTtcblxudmFyIGdub21vbmljID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBwcm9qZWN0aW9uKGdub21vbmljUmF3KVxuICAgICAgLnNjYWxlKDE0NC4wNDkpXG4gICAgICAuY2xpcEFuZ2xlKDYwKTtcbn07XG5cbmZ1bmN0aW9uIHNjYWxlVHJhbnNsYXRlKGt4LCBreSwgdHgsIHR5KSB7XG4gIHJldHVybiBreCA9PT0gMSAmJiBreSA9PT0gMSAmJiB0eCA9PT0gMCAmJiB0eSA9PT0gMCA/IGlkZW50aXR5IDogdHJhbnNmb3JtZXIoe1xuICAgIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgICB0aGlzLnN0cmVhbS5wb2ludCh4ICoga3ggKyB0eCwgeSAqIGt5ICsgdHkpO1xuICAgIH1cbiAgfSk7XG59XG5cbnZhciBpZGVudGl0eSQxID0gZnVuY3Rpb24oKSB7XG4gIHZhciBrID0gMSwgdHggPSAwLCB0eSA9IDAsIHN4ID0gMSwgc3kgPSAxLCB0cmFuc2Zvcm0kJDEgPSBpZGVudGl0eSwgLy8gc2NhbGUsIHRyYW5zbGF0ZSBhbmQgcmVmbGVjdFxuICAgICAgeDAgPSBudWxsLCB5MCwgeDEsIHkxLCAvLyBjbGlwIGV4dGVudFxuICAgICAgcG9zdGNsaXAgPSBpZGVudGl0eSxcbiAgICAgIGNhY2hlLFxuICAgICAgY2FjaGVTdHJlYW0sXG4gICAgICBwcm9qZWN0aW9uO1xuXG4gIGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgIGNhY2hlID0gY2FjaGVTdHJlYW0gPSBudWxsO1xuICAgIHJldHVybiBwcm9qZWN0aW9uO1xuICB9XG5cbiAgcmV0dXJuIHByb2plY3Rpb24gPSB7XG4gICAgc3RyZWFtOiBmdW5jdGlvbihzdHJlYW0pIHtcbiAgICAgIHJldHVybiBjYWNoZSAmJiBjYWNoZVN0cmVhbSA9PT0gc3RyZWFtID8gY2FjaGUgOiBjYWNoZSA9IHRyYW5zZm9ybSQkMShwb3N0Y2xpcChjYWNoZVN0cmVhbSA9IHN0cmVhbSkpO1xuICAgIH0sXG4gICAgcG9zdGNsaXA6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBvc3RjbGlwID0gXywgeDAgPSB5MCA9IHgxID0geTEgPSBudWxsLCByZXNldCgpKSA6IHBvc3RjbGlwO1xuICAgIH0sXG4gICAgY2xpcEV4dGVudDogZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocG9zdGNsaXAgPSBfID09IG51bGwgPyAoeDAgPSB5MCA9IHgxID0geTEgPSBudWxsLCBpZGVudGl0eSkgOiBjbGlwUmVjdGFuZ2xlKHgwID0gK19bMF1bMF0sIHkwID0gK19bMF1bMV0sIHgxID0gK19bMV1bMF0sIHkxID0gK19bMV1bMV0pLCByZXNldCgpKSA6IHgwID09IG51bGwgPyBudWxsIDogW1t4MCwgeTBdLCBbeDEsIHkxXV07XG4gICAgfSxcbiAgICBzY2FsZTogZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNmb3JtJCQxID0gc2NhbGVUcmFuc2xhdGUoKGsgPSArXykgKiBzeCwgayAqIHN5LCB0eCwgdHkpLCByZXNldCgpKSA6IGs7XG4gICAgfSxcbiAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uKF8pIHtcbiAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRyYW5zZm9ybSQkMSA9IHNjYWxlVHJhbnNsYXRlKGsgKiBzeCwgayAqIHN5LCB0eCA9ICtfWzBdLCB0eSA9ICtfWzFdKSwgcmVzZXQoKSkgOiBbdHgsIHR5XTtcbiAgICB9LFxuICAgIHJlZmxlY3RYOiBmdW5jdGlvbihfKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0cmFuc2Zvcm0kJDEgPSBzY2FsZVRyYW5zbGF0ZShrICogKHN4ID0gXyA/IC0xIDogMSksIGsgKiBzeSwgdHgsIHR5KSwgcmVzZXQoKSkgOiBzeCA8IDA7XG4gICAgfSxcbiAgICByZWZsZWN0WTogZnVuY3Rpb24oXykge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNmb3JtJCQxID0gc2NhbGVUcmFuc2xhdGUoayAqIHN4LCBrICogKHN5ID0gXyA/IC0xIDogMSksIHR4LCB0eSksIHJlc2V0KCkpIDogc3kgPCAwO1xuICAgIH0sXG4gICAgZml0RXh0ZW50OiBmdW5jdGlvbihleHRlbnQsIG9iamVjdCkge1xuICAgICAgcmV0dXJuIGZpdEV4dGVudChwcm9qZWN0aW9uLCBleHRlbnQsIG9iamVjdCk7XG4gICAgfSxcbiAgICBmaXRTaXplOiBmdW5jdGlvbihzaXplLCBvYmplY3QpIHtcbiAgICAgIHJldHVybiBmaXRTaXplKHByb2plY3Rpb24sIHNpemUsIG9iamVjdCk7XG4gICAgfSxcbiAgICBmaXRXaWR0aDogZnVuY3Rpb24od2lkdGgsIG9iamVjdCkge1xuICAgICAgcmV0dXJuIGZpdFdpZHRoKHByb2plY3Rpb24sIHdpZHRoLCBvYmplY3QpO1xuICAgIH0sXG4gICAgZml0SGVpZ2h0OiBmdW5jdGlvbihoZWlnaHQsIG9iamVjdCkge1xuICAgICAgcmV0dXJuIGZpdEhlaWdodChwcm9qZWN0aW9uLCBoZWlnaHQsIG9iamVjdCk7XG4gICAgfVxuICB9O1xufTtcblxuZnVuY3Rpb24gbmF0dXJhbEVhcnRoMVJhdyhsYW1iZGEsIHBoaSkge1xuICB2YXIgcGhpMiA9IHBoaSAqIHBoaSwgcGhpNCA9IHBoaTIgKiBwaGkyO1xuICByZXR1cm4gW1xuICAgIGxhbWJkYSAqICgwLjg3MDcgLSAwLjEzMTk3OSAqIHBoaTIgKyBwaGk0ICogKC0wLjAxMzc5MSArIHBoaTQgKiAoMC4wMDM5NzEgKiBwaGkyIC0gMC4wMDE1MjkgKiBwaGk0KSkpLFxuICAgIHBoaSAqICgxLjAwNzIyNiArIHBoaTIgKiAoMC4wMTUwODUgKyBwaGk0ICogKC0wLjA0NDQ3NSArIDAuMDI4ODc0ICogcGhpMiAtIDAuMDA1OTE2ICogcGhpNCkpKVxuICBdO1xufVxuXG5uYXR1cmFsRWFydGgxUmF3LmludmVydCA9IGZ1bmN0aW9uKHgsIHkpIHtcbiAgdmFyIHBoaSA9IHksIGkgPSAyNSwgZGVsdGE7XG4gIGRvIHtcbiAgICB2YXIgcGhpMiA9IHBoaSAqIHBoaSwgcGhpNCA9IHBoaTIgKiBwaGkyO1xuICAgIHBoaSAtPSBkZWx0YSA9IChwaGkgKiAoMS4wMDcyMjYgKyBwaGkyICogKDAuMDE1MDg1ICsgcGhpNCAqICgtMC4wNDQ0NzUgKyAwLjAyODg3NCAqIHBoaTIgLSAwLjAwNTkxNiAqIHBoaTQpKSkgLSB5KSAvXG4gICAgICAgICgxLjAwNzIyNiArIHBoaTIgKiAoMC4wMTUwODUgKiAzICsgcGhpNCAqICgtMC4wNDQ0NzUgKiA3ICsgMC4wMjg4NzQgKiA5ICogcGhpMiAtIDAuMDA1OTE2ICogMTEgKiBwaGk0KSkpO1xuICB9IHdoaWxlIChhYnMoZGVsdGEpID4gZXBzaWxvbiAmJiAtLWkgPiAwKTtcbiAgcmV0dXJuIFtcbiAgICB4IC8gKDAuODcwNyArIChwaGkyID0gcGhpICogcGhpKSAqICgtMC4xMzE5NzkgKyBwaGkyICogKC0wLjAxMzc5MSArIHBoaTIgKiBwaGkyICogcGhpMiAqICgwLjAwMzk3MSAtIDAuMDAxNTI5ICogcGhpMikpKSksXG4gICAgcGhpXG4gIF07XG59O1xuXG52YXIgbmF0dXJhbEVhcnRoMSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gcHJvamVjdGlvbihuYXR1cmFsRWFydGgxUmF3KVxuICAgICAgLnNjYWxlKDE3NS4yOTUpO1xufTtcblxuZnVuY3Rpb24gb3J0aG9ncmFwaGljUmF3KHgsIHkpIHtcbiAgcmV0dXJuIFtjb3MoeSkgKiBzaW4oeCksIHNpbih5KV07XG59XG5cbm9ydGhvZ3JhcGhpY1Jhdy5pbnZlcnQgPSBhemltdXRoYWxJbnZlcnQoYXNpbik7XG5cbnZhciBvcnRob2dyYXBoaWMgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHByb2plY3Rpb24ob3J0aG9ncmFwaGljUmF3KVxuICAgICAgLnNjYWxlKDI0OS41KVxuICAgICAgLmNsaXBBbmdsZSg5MCArIGVwc2lsb24pO1xufTtcblxuZnVuY3Rpb24gc3RlcmVvZ3JhcGhpY1Jhdyh4LCB5KSB7XG4gIHZhciBjeSA9IGNvcyh5KSwgayA9IDEgKyBjb3MoeCkgKiBjeTtcbiAgcmV0dXJuIFtjeSAqIHNpbih4KSAvIGssIHNpbih5KSAvIGtdO1xufVxuXG5zdGVyZW9ncmFwaGljUmF3LmludmVydCA9IGF6aW11dGhhbEludmVydChmdW5jdGlvbih6KSB7XG4gIHJldHVybiAyICogYXRhbih6KTtcbn0pO1xuXG52YXIgc3RlcmVvZ3JhcGhpYyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gcHJvamVjdGlvbihzdGVyZW9ncmFwaGljUmF3KVxuICAgICAgLnNjYWxlKDI1MClcbiAgICAgIC5jbGlwQW5nbGUoMTQyKTtcbn07XG5cbmZ1bmN0aW9uIHRyYW5zdmVyc2VNZXJjYXRvclJhdyhsYW1iZGEsIHBoaSkge1xuICByZXR1cm4gW2xvZyh0YW4oKGhhbGZQaSArIHBoaSkgLyAyKSksIC1sYW1iZGFdO1xufVxuXG50cmFuc3ZlcnNlTWVyY2F0b3JSYXcuaW52ZXJ0ID0gZnVuY3Rpb24oeCwgeSkge1xuICByZXR1cm4gWy15LCAyICogYXRhbihleHAoeCkpIC0gaGFsZlBpXTtcbn07XG5cbnZhciB0cmFuc3ZlcnNlTWVyY2F0b3IgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG0gPSBtZXJjYXRvclByb2plY3Rpb24odHJhbnN2ZXJzZU1lcmNhdG9yUmF3KSxcbiAgICAgIGNlbnRlciA9IG0uY2VudGVyLFxuICAgICAgcm90YXRlID0gbS5yb3RhdGU7XG5cbiAgbS5jZW50ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyBjZW50ZXIoWy1fWzFdLCBfWzBdXSkgOiAoXyA9IGNlbnRlcigpLCBbX1sxXSwgLV9bMF1dKTtcbiAgfTtcblxuICBtLnJvdGF0ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IHJvdGF0ZShbX1swXSwgX1sxXSwgXy5sZW5ndGggPiAyID8gX1syXSArIDkwIDogOTBdKSA6IChfID0gcm90YXRlKCksIFtfWzBdLCBfWzFdLCBfWzJdIC0gOTBdKTtcbiAgfTtcblxuICByZXR1cm4gcm90YXRlKFswLCAwLCA5MF0pXG4gICAgICAuc2NhbGUoMTU5LjE1NSk7XG59O1xuXG5leHBvcnRzLmdlb0FyZWEgPSBhcmVhO1xuZXhwb3J0cy5nZW9Cb3VuZHMgPSBib3VuZHM7XG5leHBvcnRzLmdlb0NlbnRyb2lkID0gY2VudHJvaWQ7XG5leHBvcnRzLmdlb0NpcmNsZSA9IGNpcmNsZTtcbmV4cG9ydHMuZ2VvQ2xpcEFudGltZXJpZGlhbiA9IGNsaXBBbnRpbWVyaWRpYW47XG5leHBvcnRzLmdlb0NsaXBDaXJjbGUgPSBjbGlwQ2lyY2xlO1xuZXhwb3J0cy5nZW9DbGlwRXh0ZW50ID0gZXh0ZW50O1xuZXhwb3J0cy5nZW9DbGlwUmVjdGFuZ2xlID0gY2xpcFJlY3RhbmdsZTtcbmV4cG9ydHMuZ2VvQ29udGFpbnMgPSBjb250YWlucztcbmV4cG9ydHMuZ2VvRGlzdGFuY2UgPSBkaXN0YW5jZTtcbmV4cG9ydHMuZ2VvR3JhdGljdWxlID0gZ3JhdGljdWxlO1xuZXhwb3J0cy5nZW9HcmF0aWN1bGUxMCA9IGdyYXRpY3VsZTEwO1xuZXhwb3J0cy5nZW9JbnRlcnBvbGF0ZSA9IGludGVycG9sYXRlO1xuZXhwb3J0cy5nZW9MZW5ndGggPSBsZW5ndGg7XG5leHBvcnRzLmdlb1BhdGggPSBpbmRleDtcbmV4cG9ydHMuZ2VvQWxiZXJzID0gYWxiZXJzO1xuZXhwb3J0cy5nZW9BbGJlcnNVc2EgPSBhbGJlcnNVc2E7XG5leHBvcnRzLmdlb0F6aW11dGhhbEVxdWFsQXJlYSA9IGF6aW11dGhhbEVxdWFsQXJlYTtcbmV4cG9ydHMuZ2VvQXppbXV0aGFsRXF1YWxBcmVhUmF3ID0gYXppbXV0aGFsRXF1YWxBcmVhUmF3O1xuZXhwb3J0cy5nZW9BemltdXRoYWxFcXVpZGlzdGFudCA9IGF6aW11dGhhbEVxdWlkaXN0YW50O1xuZXhwb3J0cy5nZW9BemltdXRoYWxFcXVpZGlzdGFudFJhdyA9IGF6aW11dGhhbEVxdWlkaXN0YW50UmF3O1xuZXhwb3J0cy5nZW9Db25pY0NvbmZvcm1hbCA9IGNvbmljQ29uZm9ybWFsO1xuZXhwb3J0cy5nZW9Db25pY0NvbmZvcm1hbFJhdyA9IGNvbmljQ29uZm9ybWFsUmF3O1xuZXhwb3J0cy5nZW9Db25pY0VxdWFsQXJlYSA9IGNvbmljRXF1YWxBcmVhO1xuZXhwb3J0cy5nZW9Db25pY0VxdWFsQXJlYVJhdyA9IGNvbmljRXF1YWxBcmVhUmF3O1xuZXhwb3J0cy5nZW9Db25pY0VxdWlkaXN0YW50ID0gY29uaWNFcXVpZGlzdGFudDtcbmV4cG9ydHMuZ2VvQ29uaWNFcXVpZGlzdGFudFJhdyA9IGNvbmljRXF1aWRpc3RhbnRSYXc7XG5leHBvcnRzLmdlb0VxdWlyZWN0YW5ndWxhciA9IGVxdWlyZWN0YW5ndWxhcjtcbmV4cG9ydHMuZ2VvRXF1aXJlY3Rhbmd1bGFyUmF3ID0gZXF1aXJlY3Rhbmd1bGFyUmF3O1xuZXhwb3J0cy5nZW9Hbm9tb25pYyA9IGdub21vbmljO1xuZXhwb3J0cy5nZW9Hbm9tb25pY1JhdyA9IGdub21vbmljUmF3O1xuZXhwb3J0cy5nZW9JZGVudGl0eSA9IGlkZW50aXR5JDE7XG5leHBvcnRzLmdlb1Byb2plY3Rpb24gPSBwcm9qZWN0aW9uO1xuZXhwb3J0cy5nZW9Qcm9qZWN0aW9uTXV0YXRvciA9IHByb2plY3Rpb25NdXRhdG9yO1xuZXhwb3J0cy5nZW9NZXJjYXRvciA9IG1lcmNhdG9yO1xuZXhwb3J0cy5nZW9NZXJjYXRvclJhdyA9IG1lcmNhdG9yUmF3O1xuZXhwb3J0cy5nZW9OYXR1cmFsRWFydGgxID0gbmF0dXJhbEVhcnRoMTtcbmV4cG9ydHMuZ2VvTmF0dXJhbEVhcnRoMVJhdyA9IG5hdHVyYWxFYXJ0aDFSYXc7XG5leHBvcnRzLmdlb09ydGhvZ3JhcGhpYyA9IG9ydGhvZ3JhcGhpYztcbmV4cG9ydHMuZ2VvT3J0aG9ncmFwaGljUmF3ID0gb3J0aG9ncmFwaGljUmF3O1xuZXhwb3J0cy5nZW9TdGVyZW9ncmFwaGljID0gc3RlcmVvZ3JhcGhpYztcbmV4cG9ydHMuZ2VvU3RlcmVvZ3JhcGhpY1JhdyA9IHN0ZXJlb2dyYXBoaWNSYXc7XG5leHBvcnRzLmdlb1RyYW5zdmVyc2VNZXJjYXRvciA9IHRyYW5zdmVyc2VNZXJjYXRvcjtcbmV4cG9ydHMuZ2VvVHJhbnN2ZXJzZU1lcmNhdG9yUmF3ID0gdHJhbnN2ZXJzZU1lcmNhdG9yUmF3O1xuZXhwb3J0cy5nZW9Sb3RhdGlvbiA9IHJvdGF0aW9uO1xuZXhwb3J0cy5nZW9TdHJlYW0gPSBnZW9TdHJlYW07XG5leHBvcnRzLmdlb1RyYW5zZm9ybSA9IHRyYW5zZm9ybTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtaGllcmFyY2h5LyBWZXJzaW9uIDEuMS41LiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXBhcmF0aW9uKGEsIGIpIHtcbiAgcmV0dXJuIGEucGFyZW50ID09PSBiLnBhcmVudCA/IDEgOiAyO1xufVxuXG5mdW5jdGlvbiBtZWFuWChjaGlsZHJlbikge1xuICByZXR1cm4gY2hpbGRyZW4ucmVkdWNlKG1lYW5YUmVkdWNlLCAwKSAvIGNoaWxkcmVuLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWVhblhSZWR1Y2UoeCwgYykge1xuICByZXR1cm4geCArIGMueDtcbn1cblxuZnVuY3Rpb24gbWF4WShjaGlsZHJlbikge1xuICByZXR1cm4gMSArIGNoaWxkcmVuLnJlZHVjZShtYXhZUmVkdWNlLCAwKTtcbn1cblxuZnVuY3Rpb24gbWF4WVJlZHVjZSh5LCBjKSB7XG4gIHJldHVybiBNYXRoLm1heCh5LCBjLnkpO1xufVxuXG5mdW5jdGlvbiBsZWFmTGVmdChub2RlKSB7XG4gIHZhciBjaGlsZHJlbjtcbiAgd2hpbGUgKGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbikgbm9kZSA9IGNoaWxkcmVuWzBdO1xuICByZXR1cm4gbm9kZTtcbn1cblxuZnVuY3Rpb24gbGVhZlJpZ2h0KG5vZGUpIHtcbiAgdmFyIGNoaWxkcmVuO1xuICB3aGlsZSAoY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuKSBub2RlID0gY2hpbGRyZW5bY2hpbGRyZW4ubGVuZ3RoIC0gMV07XG4gIHJldHVybiBub2RlO1xufVxuXG52YXIgY2x1c3RlciA9IGZ1bmN0aW9uKCkge1xuICB2YXIgc2VwYXJhdGlvbiA9IGRlZmF1bHRTZXBhcmF0aW9uLFxuICAgICAgZHggPSAxLFxuICAgICAgZHkgPSAxLFxuICAgICAgbm9kZVNpemUgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBjbHVzdGVyKHJvb3QpIHtcbiAgICB2YXIgcHJldmlvdXNOb2RlLFxuICAgICAgICB4ID0gMDtcblxuICAgIC8vIEZpcnN0IHdhbGssIGNvbXB1dGluZyB0aGUgaW5pdGlhbCB4ICYgeSB2YWx1ZXMuXG4gICAgcm9vdC5lYWNoQWZ0ZXIoZnVuY3Rpb24obm9kZSkge1xuICAgICAgdmFyIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICAgIGlmIChjaGlsZHJlbikge1xuICAgICAgICBub2RlLnggPSBtZWFuWChjaGlsZHJlbik7XG4gICAgICAgIG5vZGUueSA9IG1heFkoY2hpbGRyZW4pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9kZS54ID0gcHJldmlvdXNOb2RlID8geCArPSBzZXBhcmF0aW9uKG5vZGUsIHByZXZpb3VzTm9kZSkgOiAwO1xuICAgICAgICBub2RlLnkgPSAwO1xuICAgICAgICBwcmV2aW91c05vZGUgPSBub2RlO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdmFyIGxlZnQgPSBsZWFmTGVmdChyb290KSxcbiAgICAgICAgcmlnaHQgPSBsZWFmUmlnaHQocm9vdCksXG4gICAgICAgIHgwID0gbGVmdC54IC0gc2VwYXJhdGlvbihsZWZ0LCByaWdodCkgLyAyLFxuICAgICAgICB4MSA9IHJpZ2h0LnggKyBzZXBhcmF0aW9uKHJpZ2h0LCBsZWZ0KSAvIDI7XG5cbiAgICAvLyBTZWNvbmQgd2Fsaywgbm9ybWFsaXppbmcgeCAmIHkgdG8gdGhlIGRlc2lyZWQgc2l6ZS5cbiAgICByZXR1cm4gcm9vdC5lYWNoQWZ0ZXIobm9kZVNpemUgPyBmdW5jdGlvbihub2RlKSB7XG4gICAgICBub2RlLnggPSAobm9kZS54IC0gcm9vdC54KSAqIGR4O1xuICAgICAgbm9kZS55ID0gKHJvb3QueSAtIG5vZGUueSkgKiBkeTtcbiAgICB9IDogZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZS54ID0gKG5vZGUueCAtIHgwKSAvICh4MSAtIHgwKSAqIGR4O1xuICAgICAgbm9kZS55ID0gKDEgLSAocm9vdC55ID8gbm9kZS55IC8gcm9vdC55IDogMSkpICogZHk7XG4gICAgfSk7XG4gIH1cblxuICBjbHVzdGVyLnNlcGFyYXRpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VwYXJhdGlvbiA9IHgsIGNsdXN0ZXIpIDogc2VwYXJhdGlvbjtcbiAgfTtcblxuICBjbHVzdGVyLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZVNpemUgPSBmYWxzZSwgZHggPSAreFswXSwgZHkgPSAreFsxXSwgY2x1c3RlcikgOiAobm9kZVNpemUgPyBudWxsIDogW2R4LCBkeV0pO1xuICB9O1xuXG4gIGNsdXN0ZXIubm9kZVNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZVNpemUgPSB0cnVlLCBkeCA9ICt4WzBdLCBkeSA9ICt4WzFdLCBjbHVzdGVyKSA6IChub2RlU2l6ZSA/IFtkeCwgZHldIDogbnVsbCk7XG4gIH07XG5cbiAgcmV0dXJuIGNsdXN0ZXI7XG59O1xuXG5mdW5jdGlvbiBjb3VudChub2RlKSB7XG4gIHZhciBzdW0gPSAwLFxuICAgICAgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuLFxuICAgICAgaSA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aDtcbiAgaWYgKCFpKSBzdW0gPSAxO1xuICBlbHNlIHdoaWxlICgtLWkgPj0gMCkgc3VtICs9IGNoaWxkcmVuW2ldLnZhbHVlO1xuICBub2RlLnZhbHVlID0gc3VtO1xufVxuXG52YXIgbm9kZV9jb3VudCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5lYWNoQWZ0ZXIoY291bnQpO1xufTtcblxudmFyIG5vZGVfZWFjaCA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gIHZhciBub2RlID0gdGhpcywgY3VycmVudCwgbmV4dCA9IFtub2RlXSwgY2hpbGRyZW4sIGksIG47XG4gIGRvIHtcbiAgICBjdXJyZW50ID0gbmV4dC5yZXZlcnNlKCksIG5leHQgPSBbXTtcbiAgICB3aGlsZSAobm9kZSA9IGN1cnJlbnQucG9wKCkpIHtcbiAgICAgIGNhbGxiYWNrKG5vZGUpLCBjaGlsZHJlbiA9IG5vZGUuY2hpbGRyZW47XG4gICAgICBpZiAoY2hpbGRyZW4pIGZvciAoaSA9IDAsIG4gPSBjaGlsZHJlbi5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgICAgbmV4dC5wdXNoKGNoaWxkcmVuW2ldKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gd2hpbGUgKG5leHQubGVuZ3RoKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG52YXIgbm9kZV9lYWNoQmVmb3JlID0gZnVuY3Rpb24oY2FsbGJhY2spIHtcbiAgdmFyIG5vZGUgPSB0aGlzLCBub2RlcyA9IFtub2RlXSwgY2hpbGRyZW4sIGk7XG4gIHdoaWxlIChub2RlID0gbm9kZXMucG9wKCkpIHtcbiAgICBjYWxsYmFjayhub2RlKSwgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuO1xuICAgIGlmIChjaGlsZHJlbikgZm9yIChpID0gY2hpbGRyZW4ubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIG5vZGVzLnB1c2goY2hpbGRyZW5baV0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbnZhciBub2RlX2VhY2hBZnRlciA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gIHZhciBub2RlID0gdGhpcywgbm9kZXMgPSBbbm9kZV0sIG5leHQgPSBbXSwgY2hpbGRyZW4sIGksIG47XG4gIHdoaWxlIChub2RlID0gbm9kZXMucG9wKCkpIHtcbiAgICBuZXh0LnB1c2gobm9kZSksIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbjtcbiAgICBpZiAoY2hpbGRyZW4pIGZvciAoaSA9IDAsIG4gPSBjaGlsZHJlbi5sZW5ndGg7IGkgPCBuOyArK2kpIHtcbiAgICAgIG5vZGVzLnB1c2goY2hpbGRyZW5baV0pO1xuICAgIH1cbiAgfVxuICB3aGlsZSAobm9kZSA9IG5leHQucG9wKCkpIHtcbiAgICBjYWxsYmFjayhub2RlKTtcbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbnZhciBub2RlX3N1bSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiB0aGlzLmVhY2hBZnRlcihmdW5jdGlvbihub2RlKSB7XG4gICAgdmFyIHN1bSA9ICt2YWx1ZShub2RlLmRhdGEpIHx8IDAsXG4gICAgICAgIGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbixcbiAgICAgICAgaSA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aDtcbiAgICB3aGlsZSAoLS1pID49IDApIHN1bSArPSBjaGlsZHJlbltpXS52YWx1ZTtcbiAgICBub2RlLnZhbHVlID0gc3VtO1xuICB9KTtcbn07XG5cbnZhciBub2RlX3NvcnQgPSBmdW5jdGlvbihjb21wYXJlKSB7XG4gIHJldHVybiB0aGlzLmVhY2hCZWZvcmUoZnVuY3Rpb24obm9kZSkge1xuICAgIGlmIChub2RlLmNoaWxkcmVuKSB7XG4gICAgICBub2RlLmNoaWxkcmVuLnNvcnQoY29tcGFyZSk7XG4gICAgfVxuICB9KTtcbn07XG5cbnZhciBub2RlX3BhdGggPSBmdW5jdGlvbihlbmQpIHtcbiAgdmFyIHN0YXJ0ID0gdGhpcyxcbiAgICAgIGFuY2VzdG9yID0gbGVhc3RDb21tb25BbmNlc3RvcihzdGFydCwgZW5kKSxcbiAgICAgIG5vZGVzID0gW3N0YXJ0XTtcbiAgd2hpbGUgKHN0YXJ0ICE9PSBhbmNlc3Rvcikge1xuICAgIHN0YXJ0ID0gc3RhcnQucGFyZW50O1xuICAgIG5vZGVzLnB1c2goc3RhcnQpO1xuICB9XG4gIHZhciBrID0gbm9kZXMubGVuZ3RoO1xuICB3aGlsZSAoZW5kICE9PSBhbmNlc3Rvcikge1xuICAgIG5vZGVzLnNwbGljZShrLCAwLCBlbmQpO1xuICAgIGVuZCA9IGVuZC5wYXJlbnQ7XG4gIH1cbiAgcmV0dXJuIG5vZGVzO1xufTtcblxuZnVuY3Rpb24gbGVhc3RDb21tb25BbmNlc3RvcihhLCBiKSB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gYTtcbiAgdmFyIGFOb2RlcyA9IGEuYW5jZXN0b3JzKCksXG4gICAgICBiTm9kZXMgPSBiLmFuY2VzdG9ycygpLFxuICAgICAgYyA9IG51bGw7XG4gIGEgPSBhTm9kZXMucG9wKCk7XG4gIGIgPSBiTm9kZXMucG9wKCk7XG4gIHdoaWxlIChhID09PSBiKSB7XG4gICAgYyA9IGE7XG4gICAgYSA9IGFOb2Rlcy5wb3AoKTtcbiAgICBiID0gYk5vZGVzLnBvcCgpO1xuICB9XG4gIHJldHVybiBjO1xufVxuXG52YXIgbm9kZV9hbmNlc3RvcnMgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG5vZGUgPSB0aGlzLCBub2RlcyA9IFtub2RlXTtcbiAgd2hpbGUgKG5vZGUgPSBub2RlLnBhcmVudCkge1xuICAgIG5vZGVzLnB1c2gobm9kZSk7XG4gIH1cbiAgcmV0dXJuIG5vZGVzO1xufTtcblxudmFyIG5vZGVfZGVzY2VuZGFudHMgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG5vZGVzID0gW107XG4gIHRoaXMuZWFjaChmdW5jdGlvbihub2RlKSB7XG4gICAgbm9kZXMucHVzaChub2RlKTtcbiAgfSk7XG4gIHJldHVybiBub2Rlcztcbn07XG5cbnZhciBub2RlX2xlYXZlcyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgbGVhdmVzID0gW107XG4gIHRoaXMuZWFjaEJlZm9yZShmdW5jdGlvbihub2RlKSB7XG4gICAgaWYgKCFub2RlLmNoaWxkcmVuKSB7XG4gICAgICBsZWF2ZXMucHVzaChub2RlKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gbGVhdmVzO1xufTtcblxudmFyIG5vZGVfbGlua3MgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHJvb3QgPSB0aGlzLCBsaW5rcyA9IFtdO1xuICByb290LmVhY2goZnVuY3Rpb24obm9kZSkge1xuICAgIGlmIChub2RlICE9PSByb290KSB7IC8vIERvbuKAmXQgaW5jbHVkZSB0aGUgcm9vdOKAmXMgcGFyZW50LCBpZiBhbnkuXG4gICAgICBsaW5rcy5wdXNoKHtzb3VyY2U6IG5vZGUucGFyZW50LCB0YXJnZXQ6IG5vZGV9KTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gbGlua3M7XG59O1xuXG5mdW5jdGlvbiBoaWVyYXJjaHkoZGF0YSwgY2hpbGRyZW4pIHtcbiAgdmFyIHJvb3QgPSBuZXcgTm9kZShkYXRhKSxcbiAgICAgIHZhbHVlZCA9ICtkYXRhLnZhbHVlICYmIChyb290LnZhbHVlID0gZGF0YS52YWx1ZSksXG4gICAgICBub2RlLFxuICAgICAgbm9kZXMgPSBbcm9vdF0sXG4gICAgICBjaGlsZCxcbiAgICAgIGNoaWxkcyxcbiAgICAgIGksXG4gICAgICBuO1xuXG4gIGlmIChjaGlsZHJlbiA9PSBudWxsKSBjaGlsZHJlbiA9IGRlZmF1bHRDaGlsZHJlbjtcblxuICB3aGlsZSAobm9kZSA9IG5vZGVzLnBvcCgpKSB7XG4gICAgaWYgKHZhbHVlZCkgbm9kZS52YWx1ZSA9ICtub2RlLmRhdGEudmFsdWU7XG4gICAgaWYgKChjaGlsZHMgPSBjaGlsZHJlbihub2RlLmRhdGEpKSAmJiAobiA9IGNoaWxkcy5sZW5ndGgpKSB7XG4gICAgICBub2RlLmNoaWxkcmVuID0gbmV3IEFycmF5KG4pO1xuICAgICAgZm9yIChpID0gbiAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgIG5vZGVzLnB1c2goY2hpbGQgPSBub2RlLmNoaWxkcmVuW2ldID0gbmV3IE5vZGUoY2hpbGRzW2ldKSk7XG4gICAgICAgIGNoaWxkLnBhcmVudCA9IG5vZGU7XG4gICAgICAgIGNoaWxkLmRlcHRoID0gbm9kZS5kZXB0aCArIDE7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJvb3QuZWFjaEJlZm9yZShjb21wdXRlSGVpZ2h0KTtcbn1cblxuZnVuY3Rpb24gbm9kZV9jb3B5KCkge1xuICByZXR1cm4gaGllcmFyY2h5KHRoaXMpLmVhY2hCZWZvcmUoY29weURhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0Q2hpbGRyZW4oZCkge1xuICByZXR1cm4gZC5jaGlsZHJlbjtcbn1cblxuZnVuY3Rpb24gY29weURhdGEobm9kZSkge1xuICBub2RlLmRhdGEgPSBub2RlLmRhdGEuZGF0YTtcbn1cblxuZnVuY3Rpb24gY29tcHV0ZUhlaWdodChub2RlKSB7XG4gIHZhciBoZWlnaHQgPSAwO1xuICBkbyBub2RlLmhlaWdodCA9IGhlaWdodDtcbiAgd2hpbGUgKChub2RlID0gbm9kZS5wYXJlbnQpICYmIChub2RlLmhlaWdodCA8ICsraGVpZ2h0KSk7XG59XG5cbmZ1bmN0aW9uIE5vZGUoZGF0YSkge1xuICB0aGlzLmRhdGEgPSBkYXRhO1xuICB0aGlzLmRlcHRoID1cbiAgdGhpcy5oZWlnaHQgPSAwO1xuICB0aGlzLnBhcmVudCA9IG51bGw7XG59XG5cbk5vZGUucHJvdG90eXBlID0gaGllcmFyY2h5LnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IE5vZGUsXG4gIGNvdW50OiBub2RlX2NvdW50LFxuICBlYWNoOiBub2RlX2VhY2gsXG4gIGVhY2hBZnRlcjogbm9kZV9lYWNoQWZ0ZXIsXG4gIGVhY2hCZWZvcmU6IG5vZGVfZWFjaEJlZm9yZSxcbiAgc3VtOiBub2RlX3N1bSxcbiAgc29ydDogbm9kZV9zb3J0LFxuICBwYXRoOiBub2RlX3BhdGgsXG4gIGFuY2VzdG9yczogbm9kZV9hbmNlc3RvcnMsXG4gIGRlc2NlbmRhbnRzOiBub2RlX2Rlc2NlbmRhbnRzLFxuICBsZWF2ZXM6IG5vZGVfbGVhdmVzLFxuICBsaW5rczogbm9kZV9saW5rcyxcbiAgY29weTogbm9kZV9jb3B5XG59O1xuXG52YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbmZ1bmN0aW9uIHNodWZmbGUoYXJyYXkpIHtcbiAgdmFyIG0gPSBhcnJheS5sZW5ndGgsXG4gICAgICB0LFxuICAgICAgaTtcblxuICB3aGlsZSAobSkge1xuICAgIGkgPSBNYXRoLnJhbmRvbSgpICogbS0tIHwgMDtcbiAgICB0ID0gYXJyYXlbbV07XG4gICAgYXJyYXlbbV0gPSBhcnJheVtpXTtcbiAgICBhcnJheVtpXSA9IHQ7XG4gIH1cblxuICByZXR1cm4gYXJyYXk7XG59XG5cbnZhciBlbmNsb3NlID0gZnVuY3Rpb24oY2lyY2xlcykge1xuICB2YXIgaSA9IDAsIG4gPSAoY2lyY2xlcyA9IHNodWZmbGUoc2xpY2UuY2FsbChjaXJjbGVzKSkpLmxlbmd0aCwgQiA9IFtdLCBwLCBlO1xuXG4gIHdoaWxlIChpIDwgbikge1xuICAgIHAgPSBjaXJjbGVzW2ldO1xuICAgIGlmIChlICYmIGVuY2xvc2VzV2VhayhlLCBwKSkgKytpO1xuICAgIGVsc2UgZSA9IGVuY2xvc2VCYXNpcyhCID0gZXh0ZW5kQmFzaXMoQiwgcCkpLCBpID0gMDtcbiAgfVxuXG4gIHJldHVybiBlO1xufTtcblxuZnVuY3Rpb24gZXh0ZW5kQmFzaXMoQiwgcCkge1xuICB2YXIgaSwgajtcblxuICBpZiAoZW5jbG9zZXNXZWFrQWxsKHAsIEIpKSByZXR1cm4gW3BdO1xuXG4gIC8vIElmIHdlIGdldCBoZXJlIHRoZW4gQiBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGVsZW1lbnQuXG4gIGZvciAoaSA9IDA7IGkgPCBCLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGVuY2xvc2VzTm90KHAsIEJbaV0pXG4gICAgICAgICYmIGVuY2xvc2VzV2Vha0FsbChlbmNsb3NlQmFzaXMyKEJbaV0sIHApLCBCKSkge1xuICAgICAgcmV0dXJuIFtCW2ldLCBwXTtcbiAgICB9XG4gIH1cblxuICAvLyBJZiB3ZSBnZXQgaGVyZSB0aGVuIEIgbXVzdCBoYXZlIGF0IGxlYXN0IHR3byBlbGVtZW50cy5cbiAgZm9yIChpID0gMDsgaSA8IEIubGVuZ3RoIC0gMTsgKytpKSB7XG4gICAgZm9yIChqID0gaSArIDE7IGogPCBCLmxlbmd0aDsgKytqKSB7XG4gICAgICBpZiAoZW5jbG9zZXNOb3QoZW5jbG9zZUJhc2lzMihCW2ldLCBCW2pdKSwgcClcbiAgICAgICAgICAmJiBlbmNsb3Nlc05vdChlbmNsb3NlQmFzaXMyKEJbaV0sIHApLCBCW2pdKVxuICAgICAgICAgICYmIGVuY2xvc2VzTm90KGVuY2xvc2VCYXNpczIoQltqXSwgcCksIEJbaV0pXG4gICAgICAgICAgJiYgZW5jbG9zZXNXZWFrQWxsKGVuY2xvc2VCYXNpczMoQltpXSwgQltqXSwgcCksIEIpKSB7XG4gICAgICAgIHJldHVybiBbQltpXSwgQltqXSwgcF07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gSWYgd2UgZ2V0IGhlcmUgdGhlbiBzb21ldGhpbmcgaXMgdmVyeSB3cm9uZy5cbiAgdGhyb3cgbmV3IEVycm9yO1xufVxuXG5mdW5jdGlvbiBlbmNsb3Nlc05vdChhLCBiKSB7XG4gIHZhciBkciA9IGEuciAtIGIuciwgZHggPSBiLnggLSBhLngsIGR5ID0gYi55IC0gYS55O1xuICByZXR1cm4gZHIgPCAwIHx8IGRyICogZHIgPCBkeCAqIGR4ICsgZHkgKiBkeTtcbn1cblxuZnVuY3Rpb24gZW5jbG9zZXNXZWFrKGEsIGIpIHtcbiAgdmFyIGRyID0gYS5yIC0gYi5yICsgMWUtNiwgZHggPSBiLnggLSBhLngsIGR5ID0gYi55IC0gYS55O1xuICByZXR1cm4gZHIgPiAwICYmIGRyICogZHIgPiBkeCAqIGR4ICsgZHkgKiBkeTtcbn1cblxuZnVuY3Rpb24gZW5jbG9zZXNXZWFrQWxsKGEsIEIpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBCLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKCFlbmNsb3Nlc1dlYWsoYSwgQltpXSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGVuY2xvc2VCYXNpcyhCKSB7XG4gIHN3aXRjaCAoQi5sZW5ndGgpIHtcbiAgICBjYXNlIDE6IHJldHVybiBlbmNsb3NlQmFzaXMxKEJbMF0pO1xuICAgIGNhc2UgMjogcmV0dXJuIGVuY2xvc2VCYXNpczIoQlswXSwgQlsxXSk7XG4gICAgY2FzZSAzOiByZXR1cm4gZW5jbG9zZUJhc2lzMyhCWzBdLCBCWzFdLCBCWzJdKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBlbmNsb3NlQmFzaXMxKGEpIHtcbiAgcmV0dXJuIHtcbiAgICB4OiBhLngsXG4gICAgeTogYS55LFxuICAgIHI6IGEuclxuICB9O1xufVxuXG5mdW5jdGlvbiBlbmNsb3NlQmFzaXMyKGEsIGIpIHtcbiAgdmFyIHgxID0gYS54LCB5MSA9IGEueSwgcjEgPSBhLnIsXG4gICAgICB4MiA9IGIueCwgeTIgPSBiLnksIHIyID0gYi5yLFxuICAgICAgeDIxID0geDIgLSB4MSwgeTIxID0geTIgLSB5MSwgcjIxID0gcjIgLSByMSxcbiAgICAgIGwgPSBNYXRoLnNxcnQoeDIxICogeDIxICsgeTIxICogeTIxKTtcbiAgcmV0dXJuIHtcbiAgICB4OiAoeDEgKyB4MiArIHgyMSAvIGwgKiByMjEpIC8gMixcbiAgICB5OiAoeTEgKyB5MiArIHkyMSAvIGwgKiByMjEpIC8gMixcbiAgICByOiAobCArIHIxICsgcjIpIC8gMlxuICB9O1xufVxuXG5mdW5jdGlvbiBlbmNsb3NlQmFzaXMzKGEsIGIsIGMpIHtcbiAgdmFyIHgxID0gYS54LCB5MSA9IGEueSwgcjEgPSBhLnIsXG4gICAgICB4MiA9IGIueCwgeTIgPSBiLnksIHIyID0gYi5yLFxuICAgICAgeDMgPSBjLngsIHkzID0gYy55LCByMyA9IGMucixcbiAgICAgIGEyID0geDEgLSB4MixcbiAgICAgIGEzID0geDEgLSB4MyxcbiAgICAgIGIyID0geTEgLSB5MixcbiAgICAgIGIzID0geTEgLSB5MyxcbiAgICAgIGMyID0gcjIgLSByMSxcbiAgICAgIGMzID0gcjMgLSByMSxcbiAgICAgIGQxID0geDEgKiB4MSArIHkxICogeTEgLSByMSAqIHIxLFxuICAgICAgZDIgPSBkMSAtIHgyICogeDIgLSB5MiAqIHkyICsgcjIgKiByMixcbiAgICAgIGQzID0gZDEgLSB4MyAqIHgzIC0geTMgKiB5MyArIHIzICogcjMsXG4gICAgICBhYiA9IGEzICogYjIgLSBhMiAqIGIzLFxuICAgICAgeGEgPSAoYjIgKiBkMyAtIGIzICogZDIpIC8gKGFiICogMikgLSB4MSxcbiAgICAgIHhiID0gKGIzICogYzIgLSBiMiAqIGMzKSAvIGFiLFxuICAgICAgeWEgPSAoYTMgKiBkMiAtIGEyICogZDMpIC8gKGFiICogMikgLSB5MSxcbiAgICAgIHliID0gKGEyICogYzMgLSBhMyAqIGMyKSAvIGFiLFxuICAgICAgQSA9IHhiICogeGIgKyB5YiAqIHliIC0gMSxcbiAgICAgIEIgPSAyICogKHIxICsgeGEgKiB4YiArIHlhICogeWIpLFxuICAgICAgQyA9IHhhICogeGEgKyB5YSAqIHlhIC0gcjEgKiByMSxcbiAgICAgIHIgPSAtKEEgPyAoQiArIE1hdGguc3FydChCICogQiAtIDQgKiBBICogQykpIC8gKDIgKiBBKSA6IEMgLyBCKTtcbiAgcmV0dXJuIHtcbiAgICB4OiB4MSArIHhhICsgeGIgKiByLFxuICAgIHk6IHkxICsgeWEgKyB5YiAqIHIsXG4gICAgcjogclxuICB9O1xufVxuXG5mdW5jdGlvbiBwbGFjZShhLCBiLCBjKSB7XG4gIHZhciBheCA9IGEueCxcbiAgICAgIGF5ID0gYS55LFxuICAgICAgZGEgPSBiLnIgKyBjLnIsXG4gICAgICBkYiA9IGEuciArIGMucixcbiAgICAgIGR4ID0gYi54IC0gYXgsXG4gICAgICBkeSA9IGIueSAtIGF5LFxuICAgICAgZGMgPSBkeCAqIGR4ICsgZHkgKiBkeTtcbiAgaWYgKGRjKSB7XG4gICAgdmFyIHggPSAwLjUgKyAoKGRiICo9IGRiKSAtIChkYSAqPSBkYSkpIC8gKDIgKiBkYyksXG4gICAgICAgIHkgPSBNYXRoLnNxcnQoTWF0aC5tYXgoMCwgMiAqIGRhICogKGRiICsgZGMpIC0gKGRiIC09IGRjKSAqIGRiIC0gZGEgKiBkYSkpIC8gKDIgKiBkYyk7XG4gICAgYy54ID0gYXggKyB4ICogZHggKyB5ICogZHk7XG4gICAgYy55ID0gYXkgKyB4ICogZHkgLSB5ICogZHg7XG4gIH0gZWxzZSB7XG4gICAgYy54ID0gYXggKyBkYjtcbiAgICBjLnkgPSBheTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3RzKGEsIGIpIHtcbiAgdmFyIGR4ID0gYi54IC0gYS54LFxuICAgICAgZHkgPSBiLnkgLSBhLnksXG4gICAgICBkciA9IGEuciArIGIucjtcbiAgcmV0dXJuIGRyICogZHIgLSAxZS02ID4gZHggKiBkeCArIGR5ICogZHk7XG59XG5cbmZ1bmN0aW9uIHNjb3JlKG5vZGUpIHtcbiAgdmFyIGEgPSBub2RlLl8sXG4gICAgICBiID0gbm9kZS5uZXh0Ll8sXG4gICAgICBhYiA9IGEuciArIGIucixcbiAgICAgIGR4ID0gKGEueCAqIGIuciArIGIueCAqIGEucikgLyBhYixcbiAgICAgIGR5ID0gKGEueSAqIGIuciArIGIueSAqIGEucikgLyBhYjtcbiAgcmV0dXJuIGR4ICogZHggKyBkeSAqIGR5O1xufVxuXG5mdW5jdGlvbiBOb2RlJDEoY2lyY2xlKSB7XG4gIHRoaXMuXyA9IGNpcmNsZTtcbiAgdGhpcy5uZXh0ID0gbnVsbDtcbiAgdGhpcy5wcmV2aW91cyA9IG51bGw7XG59XG5cbmZ1bmN0aW9uIHBhY2tFbmNsb3NlKGNpcmNsZXMpIHtcbiAgaWYgKCEobiA9IGNpcmNsZXMubGVuZ3RoKSkgcmV0dXJuIDA7XG5cbiAgdmFyIGEsIGIsIGMsIG4sIGFhLCBjYSwgaSwgaiwgaywgc2osIHNrO1xuXG4gIC8vIFBsYWNlIHRoZSBmaXJzdCBjaXJjbGUuXG4gIGEgPSBjaXJjbGVzWzBdLCBhLnggPSAwLCBhLnkgPSAwO1xuICBpZiAoIShuID4gMSkpIHJldHVybiBhLnI7XG5cbiAgLy8gUGxhY2UgdGhlIHNlY29uZCBjaXJjbGUuXG4gIGIgPSBjaXJjbGVzWzFdLCBhLnggPSAtYi5yLCBiLnggPSBhLnIsIGIueSA9IDA7XG4gIGlmICghKG4gPiAyKSkgcmV0dXJuIGEuciArIGIucjtcblxuICAvLyBQbGFjZSB0aGUgdGhpcmQgY2lyY2xlLlxuICBwbGFjZShiLCBhLCBjID0gY2lyY2xlc1syXSk7XG5cbiAgLy8gSW5pdGlhbGl6ZSB0aGUgZnJvbnQtY2hhaW4gdXNpbmcgdGhlIGZpcnN0IHRocmVlIGNpcmNsZXMgYSwgYiBhbmQgYy5cbiAgYSA9IG5ldyBOb2RlJDEoYSksIGIgPSBuZXcgTm9kZSQxKGIpLCBjID0gbmV3IE5vZGUkMShjKTtcbiAgYS5uZXh0ID0gYy5wcmV2aW91cyA9IGI7XG4gIGIubmV4dCA9IGEucHJldmlvdXMgPSBjO1xuICBjLm5leHQgPSBiLnByZXZpb3VzID0gYTtcblxuICAvLyBBdHRlbXB0IHRvIHBsYWNlIGVhY2ggcmVtYWluaW5nIGNpcmNsZeKAplxuICBwYWNrOiBmb3IgKGkgPSAzOyBpIDwgbjsgKytpKSB7XG4gICAgcGxhY2UoYS5fLCBiLl8sIGMgPSBjaXJjbGVzW2ldKSwgYyA9IG5ldyBOb2RlJDEoYyk7XG5cbiAgICAvLyBGaW5kIHRoZSBjbG9zZXN0IGludGVyc2VjdGluZyBjaXJjbGUgb24gdGhlIGZyb250LWNoYWluLCBpZiBhbnkuXG4gICAgLy8g4oCcQ2xvc2VuZXNz4oCdIGlzIGRldGVybWluZWQgYnkgbGluZWFyIGRpc3RhbmNlIGFsb25nIHRoZSBmcm9udC1jaGFpbi5cbiAgICAvLyDigJxBaGVhZOKAnSBvciDigJxiZWhpbmTigJ0gaXMgbGlrZXdpc2UgZGV0ZXJtaW5lZCBieSBsaW5lYXIgZGlzdGFuY2UuXG4gICAgaiA9IGIubmV4dCwgayA9IGEucHJldmlvdXMsIHNqID0gYi5fLnIsIHNrID0gYS5fLnI7XG4gICAgZG8ge1xuICAgICAgaWYgKHNqIDw9IHNrKSB7XG4gICAgICAgIGlmIChpbnRlcnNlY3RzKGouXywgYy5fKSkge1xuICAgICAgICAgIGIgPSBqLCBhLm5leHQgPSBiLCBiLnByZXZpb3VzID0gYSwgLS1pO1xuICAgICAgICAgIGNvbnRpbnVlIHBhY2s7XG4gICAgICAgIH1cbiAgICAgICAgc2ogKz0gai5fLnIsIGogPSBqLm5leHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoaW50ZXJzZWN0cyhrLl8sIGMuXykpIHtcbiAgICAgICAgICBhID0gaywgYS5uZXh0ID0gYiwgYi5wcmV2aW91cyA9IGEsIC0taTtcbiAgICAgICAgICBjb250aW51ZSBwYWNrO1xuICAgICAgICB9XG4gICAgICAgIHNrICs9IGsuXy5yLCBrID0gay5wcmV2aW91cztcbiAgICAgIH1cbiAgICB9IHdoaWxlIChqICE9PSBrLm5leHQpO1xuXG4gICAgLy8gU3VjY2VzcyEgSW5zZXJ0IHRoZSBuZXcgY2lyY2xlIGMgYmV0d2VlbiBhIGFuZCBiLlxuICAgIGMucHJldmlvdXMgPSBhLCBjLm5leHQgPSBiLCBhLm5leHQgPSBiLnByZXZpb3VzID0gYiA9IGM7XG5cbiAgICAvLyBDb21wdXRlIHRoZSBuZXcgY2xvc2VzdCBjaXJjbGUgcGFpciB0byB0aGUgY2VudHJvaWQuXG4gICAgYWEgPSBzY29yZShhKTtcbiAgICB3aGlsZSAoKGMgPSBjLm5leHQpICE9PSBiKSB7XG4gICAgICBpZiAoKGNhID0gc2NvcmUoYykpIDwgYWEpIHtcbiAgICAgICAgYSA9IGMsIGFhID0gY2E7XG4gICAgICB9XG4gICAgfVxuICAgIGIgPSBhLm5leHQ7XG4gIH1cblxuICAvLyBDb21wdXRlIHRoZSBlbmNsb3NpbmcgY2lyY2xlIG9mIHRoZSBmcm9udCBjaGFpbi5cbiAgYSA9IFtiLl9dLCBjID0gYjsgd2hpbGUgKChjID0gYy5uZXh0KSAhPT0gYikgYS5wdXNoKGMuXyk7IGMgPSBlbmNsb3NlKGEpO1xuXG4gIC8vIFRyYW5zbGF0ZSB0aGUgY2lyY2xlcyB0byBwdXQgdGhlIGVuY2xvc2luZyBjaXJjbGUgYXJvdW5kIHRoZSBvcmlnaW4uXG4gIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIGEgPSBjaXJjbGVzW2ldLCBhLnggLT0gYy54LCBhLnkgLT0gYy55O1xuXG4gIHJldHVybiBjLnI7XG59XG5cbnZhciBzaWJsaW5ncyA9IGZ1bmN0aW9uKGNpcmNsZXMpIHtcbiAgcGFja0VuY2xvc2UoY2lyY2xlcyk7XG4gIHJldHVybiBjaXJjbGVzO1xufTtcblxuZnVuY3Rpb24gb3B0aW9uYWwoZikge1xuICByZXR1cm4gZiA9PSBudWxsID8gbnVsbCA6IHJlcXVpcmVkKGYpO1xufVxuXG5mdW5jdGlvbiByZXF1aXJlZChmKSB7XG4gIGlmICh0eXBlb2YgZiAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3I7XG4gIHJldHVybiBmO1xufVxuXG5mdW5jdGlvbiBjb25zdGFudFplcm8oKSB7XG4gIHJldHVybiAwO1xufVxuXG52YXIgY29uc3RhbnQgPSBmdW5jdGlvbih4KSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4geDtcbiAgfTtcbn07XG5cbmZ1bmN0aW9uIGRlZmF1bHRSYWRpdXMoZCkge1xuICByZXR1cm4gTWF0aC5zcXJ0KGQudmFsdWUpO1xufVxuXG52YXIgaW5kZXggPSBmdW5jdGlvbigpIHtcbiAgdmFyIHJhZGl1cyA9IG51bGwsXG4gICAgICBkeCA9IDEsXG4gICAgICBkeSA9IDEsXG4gICAgICBwYWRkaW5nID0gY29uc3RhbnRaZXJvO1xuXG4gIGZ1bmN0aW9uIHBhY2socm9vdCkge1xuICAgIHJvb3QueCA9IGR4IC8gMiwgcm9vdC55ID0gZHkgLyAyO1xuICAgIGlmIChyYWRpdXMpIHtcbiAgICAgIHJvb3QuZWFjaEJlZm9yZShyYWRpdXNMZWFmKHJhZGl1cykpXG4gICAgICAgICAgLmVhY2hBZnRlcihwYWNrQ2hpbGRyZW4ocGFkZGluZywgMC41KSlcbiAgICAgICAgICAuZWFjaEJlZm9yZSh0cmFuc2xhdGVDaGlsZCgxKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJvb3QuZWFjaEJlZm9yZShyYWRpdXNMZWFmKGRlZmF1bHRSYWRpdXMpKVxuICAgICAgICAgIC5lYWNoQWZ0ZXIocGFja0NoaWxkcmVuKGNvbnN0YW50WmVybywgMSkpXG4gICAgICAgICAgLmVhY2hBZnRlcihwYWNrQ2hpbGRyZW4ocGFkZGluZywgcm9vdC5yIC8gTWF0aC5taW4oZHgsIGR5KSkpXG4gICAgICAgICAgLmVhY2hCZWZvcmUodHJhbnNsYXRlQ2hpbGQoTWF0aC5taW4oZHgsIGR5KSAvICgyICogcm9vdC5yKSkpO1xuICAgIH1cbiAgICByZXR1cm4gcm9vdDtcbiAgfVxuXG4gIHBhY2sucmFkaXVzID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHJhZGl1cyA9IG9wdGlvbmFsKHgpLCBwYWNrKSA6IHJhZGl1cztcbiAgfTtcblxuICBwYWNrLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZHggPSAreFswXSwgZHkgPSAreFsxXSwgcGFjaykgOiBbZHgsIGR5XTtcbiAgfTtcblxuICBwYWNrLnBhZGRpbmcgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkZGluZyA9IHR5cGVvZiB4ID09PSBcImZ1bmN0aW9uXCIgPyB4IDogY29uc3RhbnQoK3gpLCBwYWNrKSA6IHBhZGRpbmc7XG4gIH07XG5cbiAgcmV0dXJuIHBhY2s7XG59O1xuXG5mdW5jdGlvbiByYWRpdXNMZWFmKHJhZGl1cykge1xuICByZXR1cm4gZnVuY3Rpb24obm9kZSkge1xuICAgIGlmICghbm9kZS5jaGlsZHJlbikge1xuICAgICAgbm9kZS5yID0gTWF0aC5tYXgoMCwgK3JhZGl1cyhub2RlKSB8fCAwKTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIHBhY2tDaGlsZHJlbihwYWRkaW5nLCBrKSB7XG4gIHJldHVybiBmdW5jdGlvbihub2RlKSB7XG4gICAgaWYgKGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlbikge1xuICAgICAgdmFyIGNoaWxkcmVuLFxuICAgICAgICAgIGksXG4gICAgICAgICAgbiA9IGNoaWxkcmVuLmxlbmd0aCxcbiAgICAgICAgICByID0gcGFkZGluZyhub2RlKSAqIGsgfHwgMCxcbiAgICAgICAgICBlO1xuXG4gICAgICBpZiAocikgZm9yIChpID0gMDsgaSA8IG47ICsraSkgY2hpbGRyZW5baV0uciArPSByO1xuICAgICAgZSA9IHBhY2tFbmNsb3NlKGNoaWxkcmVuKTtcbiAgICAgIGlmIChyKSBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSBjaGlsZHJlbltpXS5yIC09IHI7XG4gICAgICBub2RlLnIgPSBlICsgcjtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIHRyYW5zbGF0ZUNoaWxkKGspIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKG5vZGUpIHtcbiAgICB2YXIgcGFyZW50ID0gbm9kZS5wYXJlbnQ7XG4gICAgbm9kZS5yICo9IGs7XG4gICAgaWYgKHBhcmVudCkge1xuICAgICAgbm9kZS54ID0gcGFyZW50LnggKyBrICogbm9kZS54O1xuICAgICAgbm9kZS55ID0gcGFyZW50LnkgKyBrICogbm9kZS55O1xuICAgIH1cbiAgfTtcbn1cblxudmFyIHJvdW5kTm9kZSA9IGZ1bmN0aW9uKG5vZGUpIHtcbiAgbm9kZS54MCA9IE1hdGgucm91bmQobm9kZS54MCk7XG4gIG5vZGUueTAgPSBNYXRoLnJvdW5kKG5vZGUueTApO1xuICBub2RlLngxID0gTWF0aC5yb3VuZChub2RlLngxKTtcbiAgbm9kZS55MSA9IE1hdGgucm91bmQobm9kZS55MSk7XG59O1xuXG52YXIgdHJlZW1hcERpY2UgPSBmdW5jdGlvbihwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gIHZhciBub2RlcyA9IHBhcmVudC5jaGlsZHJlbixcbiAgICAgIG5vZGUsXG4gICAgICBpID0gLTEsXG4gICAgICBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgayA9IHBhcmVudC52YWx1ZSAmJiAoeDEgLSB4MCkgLyBwYXJlbnQudmFsdWU7XG5cbiAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICBub2RlID0gbm9kZXNbaV0sIG5vZGUueTAgPSB5MCwgbm9kZS55MSA9IHkxO1xuICAgIG5vZGUueDAgPSB4MCwgbm9kZS54MSA9IHgwICs9IG5vZGUudmFsdWUgKiBrO1xuICB9XG59O1xuXG52YXIgcGFydGl0aW9uID0gZnVuY3Rpb24oKSB7XG4gIHZhciBkeCA9IDEsXG4gICAgICBkeSA9IDEsXG4gICAgICBwYWRkaW5nID0gMCxcbiAgICAgIHJvdW5kID0gZmFsc2U7XG5cbiAgZnVuY3Rpb24gcGFydGl0aW9uKHJvb3QpIHtcbiAgICB2YXIgbiA9IHJvb3QuaGVpZ2h0ICsgMTtcbiAgICByb290LngwID1cbiAgICByb290LnkwID0gcGFkZGluZztcbiAgICByb290LngxID0gZHg7XG4gICAgcm9vdC55MSA9IGR5IC8gbjtcbiAgICByb290LmVhY2hCZWZvcmUocG9zaXRpb25Ob2RlKGR5LCBuKSk7XG4gICAgaWYgKHJvdW5kKSByb290LmVhY2hCZWZvcmUocm91bmROb2RlKTtcbiAgICByZXR1cm4gcm9vdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvc2l0aW9uTm9kZShkeSwgbikge1xuICAgIHJldHVybiBmdW5jdGlvbihub2RlKSB7XG4gICAgICBpZiAobm9kZS5jaGlsZHJlbikge1xuICAgICAgICB0cmVlbWFwRGljZShub2RlLCBub2RlLngwLCBkeSAqIChub2RlLmRlcHRoICsgMSkgLyBuLCBub2RlLngxLCBkeSAqIChub2RlLmRlcHRoICsgMikgLyBuKTtcbiAgICAgIH1cbiAgICAgIHZhciB4MCA9IG5vZGUueDAsXG4gICAgICAgICAgeTAgPSBub2RlLnkwLFxuICAgICAgICAgIHgxID0gbm9kZS54MSAtIHBhZGRpbmcsXG4gICAgICAgICAgeTEgPSBub2RlLnkxIC0gcGFkZGluZztcbiAgICAgIGlmICh4MSA8IHgwKSB4MCA9IHgxID0gKHgwICsgeDEpIC8gMjtcbiAgICAgIGlmICh5MSA8IHkwKSB5MCA9IHkxID0gKHkwICsgeTEpIC8gMjtcbiAgICAgIG5vZGUueDAgPSB4MDtcbiAgICAgIG5vZGUueTAgPSB5MDtcbiAgICAgIG5vZGUueDEgPSB4MTtcbiAgICAgIG5vZGUueTEgPSB5MTtcbiAgICB9O1xuICB9XG5cbiAgcGFydGl0aW9uLnJvdW5kID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHJvdW5kID0gISF4LCBwYXJ0aXRpb24pIDogcm91bmQ7XG4gIH07XG5cbiAgcGFydGl0aW9uLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZHggPSAreFswXSwgZHkgPSAreFsxXSwgcGFydGl0aW9uKSA6IFtkeCwgZHldO1xuICB9O1xuXG4gIHBhcnRpdGlvbi5wYWRkaW5nID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBhZGRpbmcgPSAreCwgcGFydGl0aW9uKSA6IHBhZGRpbmc7XG4gIH07XG5cbiAgcmV0dXJuIHBhcnRpdGlvbjtcbn07XG5cbnZhciBrZXlQcmVmaXggPSBcIiRcIjtcbnZhciBwcmVyb290ID0ge2RlcHRoOiAtMX07XG52YXIgYW1iaWd1b3VzID0ge307XG5cbmZ1bmN0aW9uIGRlZmF1bHRJZChkKSB7XG4gIHJldHVybiBkLmlkO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0UGFyZW50SWQoZCkge1xuICByZXR1cm4gZC5wYXJlbnRJZDtcbn1cblxudmFyIHN0cmF0aWZ5ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBpZCA9IGRlZmF1bHRJZCxcbiAgICAgIHBhcmVudElkID0gZGVmYXVsdFBhcmVudElkO1xuXG4gIGZ1bmN0aW9uIHN0cmF0aWZ5KGRhdGEpIHtcbiAgICB2YXIgZCxcbiAgICAgICAgaSxcbiAgICAgICAgbiA9IGRhdGEubGVuZ3RoLFxuICAgICAgICByb290LFxuICAgICAgICBwYXJlbnQsXG4gICAgICAgIG5vZGUsXG4gICAgICAgIG5vZGVzID0gbmV3IEFycmF5KG4pLFxuICAgICAgICBub2RlSWQsXG4gICAgICAgIG5vZGVLZXksXG4gICAgICAgIG5vZGVCeUtleSA9IHt9O1xuXG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgZCA9IGRhdGFbaV0sIG5vZGUgPSBub2Rlc1tpXSA9IG5ldyBOb2RlKGQpO1xuICAgICAgaWYgKChub2RlSWQgPSBpZChkLCBpLCBkYXRhKSkgIT0gbnVsbCAmJiAobm9kZUlkICs9IFwiXCIpKSB7XG4gICAgICAgIG5vZGVLZXkgPSBrZXlQcmVmaXggKyAobm9kZS5pZCA9IG5vZGVJZCk7XG4gICAgICAgIG5vZGVCeUtleVtub2RlS2V5XSA9IG5vZGVLZXkgaW4gbm9kZUJ5S2V5ID8gYW1iaWd1b3VzIDogbm9kZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBub2RlID0gbm9kZXNbaV0sIG5vZGVJZCA9IHBhcmVudElkKGRhdGFbaV0sIGksIGRhdGEpO1xuICAgICAgaWYgKG5vZGVJZCA9PSBudWxsIHx8ICEobm9kZUlkICs9IFwiXCIpKSB7XG4gICAgICAgIGlmIChyb290KSB0aHJvdyBuZXcgRXJyb3IoXCJtdWx0aXBsZSByb290c1wiKTtcbiAgICAgICAgcm9vdCA9IG5vZGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXJlbnQgPSBub2RlQnlLZXlba2V5UHJlZml4ICsgbm9kZUlkXTtcbiAgICAgICAgaWYgKCFwYXJlbnQpIHRocm93IG5ldyBFcnJvcihcIm1pc3Npbmc6IFwiICsgbm9kZUlkKTtcbiAgICAgICAgaWYgKHBhcmVudCA9PT0gYW1iaWd1b3VzKSB0aHJvdyBuZXcgRXJyb3IoXCJhbWJpZ3VvdXM6IFwiICsgbm9kZUlkKTtcbiAgICAgICAgaWYgKHBhcmVudC5jaGlsZHJlbikgcGFyZW50LmNoaWxkcmVuLnB1c2gobm9kZSk7XG4gICAgICAgIGVsc2UgcGFyZW50LmNoaWxkcmVuID0gW25vZGVdO1xuICAgICAgICBub2RlLnBhcmVudCA9IHBhcmVudDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXJvb3QpIHRocm93IG5ldyBFcnJvcihcIm5vIHJvb3RcIik7XG4gICAgcm9vdC5wYXJlbnQgPSBwcmVyb290O1xuICAgIHJvb3QuZWFjaEJlZm9yZShmdW5jdGlvbihub2RlKSB7IG5vZGUuZGVwdGggPSBub2RlLnBhcmVudC5kZXB0aCArIDE7IC0tbjsgfSkuZWFjaEJlZm9yZShjb21wdXRlSGVpZ2h0KTtcbiAgICByb290LnBhcmVudCA9IG51bGw7XG4gICAgaWYgKG4gPiAwKSB0aHJvdyBuZXcgRXJyb3IoXCJjeWNsZVwiKTtcblxuICAgIHJldHVybiByb290O1xuICB9XG5cbiAgc3RyYXRpZnkuaWQgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaWQgPSByZXF1aXJlZCh4KSwgc3RyYXRpZnkpIDogaWQ7XG4gIH07XG5cbiAgc3RyYXRpZnkucGFyZW50SWQgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFyZW50SWQgPSByZXF1aXJlZCh4KSwgc3RyYXRpZnkpIDogcGFyZW50SWQ7XG4gIH07XG5cbiAgcmV0dXJuIHN0cmF0aWZ5O1xufTtcblxuZnVuY3Rpb24gZGVmYXVsdFNlcGFyYXRpb24kMShhLCBiKSB7XG4gIHJldHVybiBhLnBhcmVudCA9PT0gYi5wYXJlbnQgPyAxIDogMjtcbn1cblxuLy8gZnVuY3Rpb24gcmFkaWFsU2VwYXJhdGlvbihhLCBiKSB7XG4vLyAgIHJldHVybiAoYS5wYXJlbnQgPT09IGIucGFyZW50ID8gMSA6IDIpIC8gYS5kZXB0aDtcbi8vIH1cblxuLy8gVGhpcyBmdW5jdGlvbiBpcyB1c2VkIHRvIHRyYXZlcnNlIHRoZSBsZWZ0IGNvbnRvdXIgb2YgYSBzdWJ0cmVlIChvclxuLy8gc3ViZm9yZXN0KS4gSXQgcmV0dXJucyB0aGUgc3VjY2Vzc29yIG9mIHYgb24gdGhpcyBjb250b3VyLiBUaGlzIHN1Y2Nlc3NvciBpc1xuLy8gZWl0aGVyIGdpdmVuIGJ5IHRoZSBsZWZ0bW9zdCBjaGlsZCBvZiB2IG9yIGJ5IHRoZSB0aHJlYWQgb2Ygdi4gVGhlIGZ1bmN0aW9uXG4vLyByZXR1cm5zIG51bGwgaWYgYW5kIG9ubHkgaWYgdiBpcyBvbiB0aGUgaGlnaGVzdCBsZXZlbCBvZiBpdHMgc3VidHJlZS5cbmZ1bmN0aW9uIG5leHRMZWZ0KHYpIHtcbiAgdmFyIGNoaWxkcmVuID0gdi5jaGlsZHJlbjtcbiAgcmV0dXJuIGNoaWxkcmVuID8gY2hpbGRyZW5bMF0gOiB2LnQ7XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gd29ya3MgYW5hbG9nb3VzbHkgdG8gbmV4dExlZnQuXG5mdW5jdGlvbiBuZXh0UmlnaHQodikge1xuICB2YXIgY2hpbGRyZW4gPSB2LmNoaWxkcmVuO1xuICByZXR1cm4gY2hpbGRyZW4gPyBjaGlsZHJlbltjaGlsZHJlbi5sZW5ndGggLSAxXSA6IHYudDtcbn1cblxuLy8gU2hpZnRzIHRoZSBjdXJyZW50IHN1YnRyZWUgcm9vdGVkIGF0IHcrLiBUaGlzIGlzIGRvbmUgYnkgaW5jcmVhc2luZ1xuLy8gcHJlbGltKHcrKSBhbmQgbW9kKHcrKSBieSBzaGlmdC5cbmZ1bmN0aW9uIG1vdmVTdWJ0cmVlKHdtLCB3cCwgc2hpZnQpIHtcbiAgdmFyIGNoYW5nZSA9IHNoaWZ0IC8gKHdwLmkgLSB3bS5pKTtcbiAgd3AuYyAtPSBjaGFuZ2U7XG4gIHdwLnMgKz0gc2hpZnQ7XG4gIHdtLmMgKz0gY2hhbmdlO1xuICB3cC56ICs9IHNoaWZ0O1xuICB3cC5tICs9IHNoaWZ0O1xufVxuXG4vLyBBbGwgb3RoZXIgc2hpZnRzLCBhcHBsaWVkIHRvIHRoZSBzbWFsbGVyIHN1YnRyZWVzIGJldHdlZW4gdy0gYW5kIHcrLCBhcmVcbi8vIHBlcmZvcm1lZCBieSB0aGlzIGZ1bmN0aW9uLiBUbyBwcmVwYXJlIHRoZSBzaGlmdHMsIHdlIGhhdmUgdG8gYWRqdXN0XG4vLyBjaGFuZ2UodyspLCBzaGlmdCh3KyksIGFuZCBjaGFuZ2Uody0pLlxuZnVuY3Rpb24gZXhlY3V0ZVNoaWZ0cyh2KSB7XG4gIHZhciBzaGlmdCA9IDAsXG4gICAgICBjaGFuZ2UgPSAwLFxuICAgICAgY2hpbGRyZW4gPSB2LmNoaWxkcmVuLFxuICAgICAgaSA9IGNoaWxkcmVuLmxlbmd0aCxcbiAgICAgIHc7XG4gIHdoaWxlICgtLWkgPj0gMCkge1xuICAgIHcgPSBjaGlsZHJlbltpXTtcbiAgICB3LnogKz0gc2hpZnQ7XG4gICAgdy5tICs9IHNoaWZ0O1xuICAgIHNoaWZ0ICs9IHcucyArIChjaGFuZ2UgKz0gdy5jKTtcbiAgfVxufVxuXG4vLyBJZiB2aS3igJlzIGFuY2VzdG9yIGlzIGEgc2libGluZyBvZiB2LCByZXR1cm5zIHZpLeKAmXMgYW5jZXN0b3IuIE90aGVyd2lzZSxcbi8vIHJldHVybnMgdGhlIHNwZWNpZmllZCAoZGVmYXVsdCkgYW5jZXN0b3IuXG5mdW5jdGlvbiBuZXh0QW5jZXN0b3IodmltLCB2LCBhbmNlc3Rvcikge1xuICByZXR1cm4gdmltLmEucGFyZW50ID09PSB2LnBhcmVudCA/IHZpbS5hIDogYW5jZXN0b3I7XG59XG5cbmZ1bmN0aW9uIFRyZWVOb2RlKG5vZGUsIGkpIHtcbiAgdGhpcy5fID0gbm9kZTtcbiAgdGhpcy5wYXJlbnQgPSBudWxsO1xuICB0aGlzLmNoaWxkcmVuID0gbnVsbDtcbiAgdGhpcy5BID0gbnVsbDsgLy8gZGVmYXVsdCBhbmNlc3RvclxuICB0aGlzLmEgPSB0aGlzOyAvLyBhbmNlc3RvclxuICB0aGlzLnogPSAwOyAvLyBwcmVsaW1cbiAgdGhpcy5tID0gMDsgLy8gbW9kXG4gIHRoaXMuYyA9IDA7IC8vIGNoYW5nZVxuICB0aGlzLnMgPSAwOyAvLyBzaGlmdFxuICB0aGlzLnQgPSBudWxsOyAvLyB0aHJlYWRcbiAgdGhpcy5pID0gaTsgLy8gbnVtYmVyXG59XG5cblRyZWVOb2RlLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoTm9kZS5wcm90b3R5cGUpO1xuXG5mdW5jdGlvbiB0cmVlUm9vdChyb290KSB7XG4gIHZhciB0cmVlID0gbmV3IFRyZWVOb2RlKHJvb3QsIDApLFxuICAgICAgbm9kZSxcbiAgICAgIG5vZGVzID0gW3RyZWVdLFxuICAgICAgY2hpbGQsXG4gICAgICBjaGlsZHJlbixcbiAgICAgIGksXG4gICAgICBuO1xuXG4gIHdoaWxlIChub2RlID0gbm9kZXMucG9wKCkpIHtcbiAgICBpZiAoY2hpbGRyZW4gPSBub2RlLl8uY2hpbGRyZW4pIHtcbiAgICAgIG5vZGUuY2hpbGRyZW4gPSBuZXcgQXJyYXkobiA9IGNoaWxkcmVuLmxlbmd0aCk7XG4gICAgICBmb3IgKGkgPSBuIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgbm9kZXMucHVzaChjaGlsZCA9IG5vZGUuY2hpbGRyZW5baV0gPSBuZXcgVHJlZU5vZGUoY2hpbGRyZW5baV0sIGkpKTtcbiAgICAgICAgY2hpbGQucGFyZW50ID0gbm9kZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAodHJlZS5wYXJlbnQgPSBuZXcgVHJlZU5vZGUobnVsbCwgMCkpLmNoaWxkcmVuID0gW3RyZWVdO1xuICByZXR1cm4gdHJlZTtcbn1cblxuLy8gTm9kZS1saW5rIHRyZWUgZGlhZ3JhbSB1c2luZyB0aGUgUmVpbmdvbGQtVGlsZm9yZCBcInRpZHlcIiBhbGdvcml0aG1cbnZhciB0cmVlID0gZnVuY3Rpb24oKSB7XG4gIHZhciBzZXBhcmF0aW9uID0gZGVmYXVsdFNlcGFyYXRpb24kMSxcbiAgICAgIGR4ID0gMSxcbiAgICAgIGR5ID0gMSxcbiAgICAgIG5vZGVTaXplID0gbnVsbDtcblxuICBmdW5jdGlvbiB0cmVlKHJvb3QpIHtcbiAgICB2YXIgdCA9IHRyZWVSb290KHJvb3QpO1xuXG4gICAgLy8gQ29tcHV0ZSB0aGUgbGF5b3V0IHVzaW5nIEJ1Y2hoZWltIGV0IGFsLuKAmXMgYWxnb3JpdGhtLlxuICAgIHQuZWFjaEFmdGVyKGZpcnN0V2FsayksIHQucGFyZW50Lm0gPSAtdC56O1xuICAgIHQuZWFjaEJlZm9yZShzZWNvbmRXYWxrKTtcblxuICAgIC8vIElmIGEgZml4ZWQgbm9kZSBzaXplIGlzIHNwZWNpZmllZCwgc2NhbGUgeCBhbmQgeS5cbiAgICBpZiAobm9kZVNpemUpIHJvb3QuZWFjaEJlZm9yZShzaXplTm9kZSk7XG5cbiAgICAvLyBJZiBhIGZpeGVkIHRyZWUgc2l6ZSBpcyBzcGVjaWZpZWQsIHNjYWxlIHggYW5kIHkgYmFzZWQgb24gdGhlIGV4dGVudC5cbiAgICAvLyBDb21wdXRlIHRoZSBsZWZ0LW1vc3QsIHJpZ2h0LW1vc3QsIGFuZCBkZXB0aC1tb3N0IG5vZGVzIGZvciBleHRlbnRzLlxuICAgIGVsc2Uge1xuICAgICAgdmFyIGxlZnQgPSByb290LFxuICAgICAgICAgIHJpZ2h0ID0gcm9vdCxcbiAgICAgICAgICBib3R0b20gPSByb290O1xuICAgICAgcm9vdC5lYWNoQmVmb3JlKGZ1bmN0aW9uKG5vZGUpIHtcbiAgICAgICAgaWYgKG5vZGUueCA8IGxlZnQueCkgbGVmdCA9IG5vZGU7XG4gICAgICAgIGlmIChub2RlLnggPiByaWdodC54KSByaWdodCA9IG5vZGU7XG4gICAgICAgIGlmIChub2RlLmRlcHRoID4gYm90dG9tLmRlcHRoKSBib3R0b20gPSBub2RlO1xuICAgICAgfSk7XG4gICAgICB2YXIgcyA9IGxlZnQgPT09IHJpZ2h0ID8gMSA6IHNlcGFyYXRpb24obGVmdCwgcmlnaHQpIC8gMixcbiAgICAgICAgICB0eCA9IHMgLSBsZWZ0LngsXG4gICAgICAgICAga3ggPSBkeCAvIChyaWdodC54ICsgcyArIHR4KSxcbiAgICAgICAgICBreSA9IGR5IC8gKGJvdHRvbS5kZXB0aCB8fCAxKTtcbiAgICAgIHJvb3QuZWFjaEJlZm9yZShmdW5jdGlvbihub2RlKSB7XG4gICAgICAgIG5vZGUueCA9IChub2RlLnggKyB0eCkgKiBreDtcbiAgICAgICAgbm9kZS55ID0gbm9kZS5kZXB0aCAqIGt5O1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvb3Q7XG4gIH1cblxuICAvLyBDb21wdXRlcyBhIHByZWxpbWluYXJ5IHgtY29vcmRpbmF0ZSBmb3Igdi4gQmVmb3JlIHRoYXQsIEZJUlNUIFdBTEsgaXNcbiAgLy8gYXBwbGllZCByZWN1cnNpdmVseSB0byB0aGUgY2hpbGRyZW4gb2YgdiwgYXMgd2VsbCBhcyB0aGUgZnVuY3Rpb25cbiAgLy8gQVBQT1JUSU9OLiBBZnRlciBzcGFjaW5nIG91dCB0aGUgY2hpbGRyZW4gYnkgY2FsbGluZyBFWEVDVVRFIFNISUZUUywgdGhlXG4gIC8vIG5vZGUgdiBpcyBwbGFjZWQgdG8gdGhlIG1pZHBvaW50IG9mIGl0cyBvdXRlcm1vc3QgY2hpbGRyZW4uXG4gIGZ1bmN0aW9uIGZpcnN0V2Fsayh2KSB7XG4gICAgdmFyIGNoaWxkcmVuID0gdi5jaGlsZHJlbixcbiAgICAgICAgc2libGluZ3MgPSB2LnBhcmVudC5jaGlsZHJlbixcbiAgICAgICAgdyA9IHYuaSA/IHNpYmxpbmdzW3YuaSAtIDFdIDogbnVsbDtcbiAgICBpZiAoY2hpbGRyZW4pIHtcbiAgICAgIGV4ZWN1dGVTaGlmdHModik7XG4gICAgICB2YXIgbWlkcG9pbnQgPSAoY2hpbGRyZW5bMF0ueiArIGNoaWxkcmVuW2NoaWxkcmVuLmxlbmd0aCAtIDFdLnopIC8gMjtcbiAgICAgIGlmICh3KSB7XG4gICAgICAgIHYueiA9IHcueiArIHNlcGFyYXRpb24odi5fLCB3Ll8pO1xuICAgICAgICB2Lm0gPSB2LnogLSBtaWRwb2ludDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHYueiA9IG1pZHBvaW50O1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodykge1xuICAgICAgdi56ID0gdy56ICsgc2VwYXJhdGlvbih2Ll8sIHcuXyk7XG4gICAgfVxuICAgIHYucGFyZW50LkEgPSBhcHBvcnRpb24odiwgdywgdi5wYXJlbnQuQSB8fCBzaWJsaW5nc1swXSk7XG4gIH1cblxuICAvLyBDb21wdXRlcyBhbGwgcmVhbCB4LWNvb3JkaW5hdGVzIGJ5IHN1bW1pbmcgdXAgdGhlIG1vZGlmaWVycyByZWN1cnNpdmVseS5cbiAgZnVuY3Rpb24gc2Vjb25kV2Fsayh2KSB7XG4gICAgdi5fLnggPSB2LnogKyB2LnBhcmVudC5tO1xuICAgIHYubSArPSB2LnBhcmVudC5tO1xuICB9XG5cbiAgLy8gVGhlIGNvcmUgb2YgdGhlIGFsZ29yaXRobS4gSGVyZSwgYSBuZXcgc3VidHJlZSBpcyBjb21iaW5lZCB3aXRoIHRoZVxuICAvLyBwcmV2aW91cyBzdWJ0cmVlcy4gVGhyZWFkcyBhcmUgdXNlZCB0byB0cmF2ZXJzZSB0aGUgaW5zaWRlIGFuZCBvdXRzaWRlXG4gIC8vIGNvbnRvdXJzIG9mIHRoZSBsZWZ0IGFuZCByaWdodCBzdWJ0cmVlIHVwIHRvIHRoZSBoaWdoZXN0IGNvbW1vbiBsZXZlbC4gVGhlXG4gIC8vIHZlcnRpY2VzIHVzZWQgZm9yIHRoZSB0cmF2ZXJzYWxzIGFyZSB2aSssIHZpLSwgdm8tLCBhbmQgdm8rLCB3aGVyZSB0aGVcbiAgLy8gc3VwZXJzY3JpcHQgbyBtZWFucyBvdXRzaWRlIGFuZCBpIG1lYW5zIGluc2lkZSwgdGhlIHN1YnNjcmlwdCAtIG1lYW5zIGxlZnRcbiAgLy8gc3VidHJlZSBhbmQgKyBtZWFucyByaWdodCBzdWJ0cmVlLiBGb3Igc3VtbWluZyB1cCB0aGUgbW9kaWZpZXJzIGFsb25nIHRoZVxuICAvLyBjb250b3VyLCB3ZSB1c2UgcmVzcGVjdGl2ZSB2YXJpYWJsZXMgc2krLCBzaS0sIHNvLSwgYW5kIHNvKy4gV2hlbmV2ZXIgdHdvXG4gIC8vIG5vZGVzIG9mIHRoZSBpbnNpZGUgY29udG91cnMgY29uZmxpY3QsIHdlIGNvbXB1dGUgdGhlIGxlZnQgb25lIG9mIHRoZVxuICAvLyBncmVhdGVzdCB1bmNvbW1vbiBhbmNlc3RvcnMgdXNpbmcgdGhlIGZ1bmN0aW9uIEFOQ0VTVE9SIGFuZCBjYWxsIE1PVkVcbiAgLy8gU1VCVFJFRSB0byBzaGlmdCB0aGUgc3VidHJlZSBhbmQgcHJlcGFyZSB0aGUgc2hpZnRzIG9mIHNtYWxsZXIgc3VidHJlZXMuXG4gIC8vIEZpbmFsbHksIHdlIGFkZCBhIG5ldyB0aHJlYWQgKGlmIG5lY2Vzc2FyeSkuXG4gIGZ1bmN0aW9uIGFwcG9ydGlvbih2LCB3LCBhbmNlc3Rvcikge1xuICAgIGlmICh3KSB7XG4gICAgICB2YXIgdmlwID0gdixcbiAgICAgICAgICB2b3AgPSB2LFxuICAgICAgICAgIHZpbSA9IHcsXG4gICAgICAgICAgdm9tID0gdmlwLnBhcmVudC5jaGlsZHJlblswXSxcbiAgICAgICAgICBzaXAgPSB2aXAubSxcbiAgICAgICAgICBzb3AgPSB2b3AubSxcbiAgICAgICAgICBzaW0gPSB2aW0ubSxcbiAgICAgICAgICBzb20gPSB2b20ubSxcbiAgICAgICAgICBzaGlmdDtcbiAgICAgIHdoaWxlICh2aW0gPSBuZXh0UmlnaHQodmltKSwgdmlwID0gbmV4dExlZnQodmlwKSwgdmltICYmIHZpcCkge1xuICAgICAgICB2b20gPSBuZXh0TGVmdCh2b20pO1xuICAgICAgICB2b3AgPSBuZXh0UmlnaHQodm9wKTtcbiAgICAgICAgdm9wLmEgPSB2O1xuICAgICAgICBzaGlmdCA9IHZpbS56ICsgc2ltIC0gdmlwLnogLSBzaXAgKyBzZXBhcmF0aW9uKHZpbS5fLCB2aXAuXyk7XG4gICAgICAgIGlmIChzaGlmdCA+IDApIHtcbiAgICAgICAgICBtb3ZlU3VidHJlZShuZXh0QW5jZXN0b3IodmltLCB2LCBhbmNlc3RvciksIHYsIHNoaWZ0KTtcbiAgICAgICAgICBzaXAgKz0gc2hpZnQ7XG4gICAgICAgICAgc29wICs9IHNoaWZ0O1xuICAgICAgICB9XG4gICAgICAgIHNpbSArPSB2aW0ubTtcbiAgICAgICAgc2lwICs9IHZpcC5tO1xuICAgICAgICBzb20gKz0gdm9tLm07XG4gICAgICAgIHNvcCArPSB2b3AubTtcbiAgICAgIH1cbiAgICAgIGlmICh2aW0gJiYgIW5leHRSaWdodCh2b3ApKSB7XG4gICAgICAgIHZvcC50ID0gdmltO1xuICAgICAgICB2b3AubSArPSBzaW0gLSBzb3A7XG4gICAgICB9XG4gICAgICBpZiAodmlwICYmICFuZXh0TGVmdCh2b20pKSB7XG4gICAgICAgIHZvbS50ID0gdmlwO1xuICAgICAgICB2b20ubSArPSBzaXAgLSBzb207XG4gICAgICAgIGFuY2VzdG9yID0gdjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFuY2VzdG9yO1xuICB9XG5cbiAgZnVuY3Rpb24gc2l6ZU5vZGUobm9kZSkge1xuICAgIG5vZGUueCAqPSBkeDtcbiAgICBub2RlLnkgPSBub2RlLmRlcHRoICogZHk7XG4gIH1cblxuICB0cmVlLnNlcGFyYXRpb24gPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc2VwYXJhdGlvbiA9IHgsIHRyZWUpIDogc2VwYXJhdGlvbjtcbiAgfTtcblxuICB0cmVlLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZVNpemUgPSBmYWxzZSwgZHggPSAreFswXSwgZHkgPSAreFsxXSwgdHJlZSkgOiAobm9kZVNpemUgPyBudWxsIDogW2R4LCBkeV0pO1xuICB9O1xuXG4gIHRyZWUubm9kZVNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobm9kZVNpemUgPSB0cnVlLCBkeCA9ICt4WzBdLCBkeSA9ICt4WzFdLCB0cmVlKSA6IChub2RlU2l6ZSA/IFtkeCwgZHldIDogbnVsbCk7XG4gIH07XG5cbiAgcmV0dXJuIHRyZWU7XG59O1xuXG52YXIgdHJlZW1hcFNsaWNlID0gZnVuY3Rpb24ocGFyZW50LCB4MCwgeTAsIHgxLCB5MSkge1xuICB2YXIgbm9kZXMgPSBwYXJlbnQuY2hpbGRyZW4sXG4gICAgICBub2RlLFxuICAgICAgaSA9IC0xLFxuICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgIGsgPSBwYXJlbnQudmFsdWUgJiYgKHkxIC0geTApIC8gcGFyZW50LnZhbHVlO1xuXG4gIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgbm9kZSA9IG5vZGVzW2ldLCBub2RlLngwID0geDAsIG5vZGUueDEgPSB4MTtcbiAgICBub2RlLnkwID0geTAsIG5vZGUueTEgPSB5MCArPSBub2RlLnZhbHVlICogaztcbiAgfVxufTtcblxudmFyIHBoaSA9ICgxICsgTWF0aC5zcXJ0KDUpKSAvIDI7XG5cbmZ1bmN0aW9uIHNxdWFyaWZ5UmF0aW8ocmF0aW8sIHBhcmVudCwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgdmFyIHJvd3MgPSBbXSxcbiAgICAgIG5vZGVzID0gcGFyZW50LmNoaWxkcmVuLFxuICAgICAgcm93LFxuICAgICAgbm9kZVZhbHVlLFxuICAgICAgaTAgPSAwLFxuICAgICAgaTEgPSAwLFxuICAgICAgbiA9IG5vZGVzLmxlbmd0aCxcbiAgICAgIGR4LCBkeSxcbiAgICAgIHZhbHVlID0gcGFyZW50LnZhbHVlLFxuICAgICAgc3VtVmFsdWUsXG4gICAgICBtaW5WYWx1ZSxcbiAgICAgIG1heFZhbHVlLFxuICAgICAgbmV3UmF0aW8sXG4gICAgICBtaW5SYXRpbyxcbiAgICAgIGFscGhhLFxuICAgICAgYmV0YTtcblxuICB3aGlsZSAoaTAgPCBuKSB7XG4gICAgZHggPSB4MSAtIHgwLCBkeSA9IHkxIC0geTA7XG5cbiAgICAvLyBGaW5kIHRoZSBuZXh0IG5vbi1lbXB0eSBub2RlLlxuICAgIGRvIHN1bVZhbHVlID0gbm9kZXNbaTErK10udmFsdWU7IHdoaWxlICghc3VtVmFsdWUgJiYgaTEgPCBuKTtcbiAgICBtaW5WYWx1ZSA9IG1heFZhbHVlID0gc3VtVmFsdWU7XG4gICAgYWxwaGEgPSBNYXRoLm1heChkeSAvIGR4LCBkeCAvIGR5KSAvICh2YWx1ZSAqIHJhdGlvKTtcbiAgICBiZXRhID0gc3VtVmFsdWUgKiBzdW1WYWx1ZSAqIGFscGhhO1xuICAgIG1pblJhdGlvID0gTWF0aC5tYXgobWF4VmFsdWUgLyBiZXRhLCBiZXRhIC8gbWluVmFsdWUpO1xuXG4gICAgLy8gS2VlcCBhZGRpbmcgbm9kZXMgd2hpbGUgdGhlIGFzcGVjdCByYXRpbyBtYWludGFpbnMgb3IgaW1wcm92ZXMuXG4gICAgZm9yICg7IGkxIDwgbjsgKytpMSkge1xuICAgICAgc3VtVmFsdWUgKz0gbm9kZVZhbHVlID0gbm9kZXNbaTFdLnZhbHVlO1xuICAgICAgaWYgKG5vZGVWYWx1ZSA8IG1pblZhbHVlKSBtaW5WYWx1ZSA9IG5vZGVWYWx1ZTtcbiAgICAgIGlmIChub2RlVmFsdWUgPiBtYXhWYWx1ZSkgbWF4VmFsdWUgPSBub2RlVmFsdWU7XG4gICAgICBiZXRhID0gc3VtVmFsdWUgKiBzdW1WYWx1ZSAqIGFscGhhO1xuICAgICAgbmV3UmF0aW8gPSBNYXRoLm1heChtYXhWYWx1ZSAvIGJldGEsIGJldGEgLyBtaW5WYWx1ZSk7XG4gICAgICBpZiAobmV3UmF0aW8gPiBtaW5SYXRpbykgeyBzdW1WYWx1ZSAtPSBub2RlVmFsdWU7IGJyZWFrOyB9XG4gICAgICBtaW5SYXRpbyA9IG5ld1JhdGlvO1xuICAgIH1cblxuICAgIC8vIFBvc2l0aW9uIGFuZCByZWNvcmQgdGhlIHJvdyBvcmllbnRhdGlvbi5cbiAgICByb3dzLnB1c2gocm93ID0ge3ZhbHVlOiBzdW1WYWx1ZSwgZGljZTogZHggPCBkeSwgY2hpbGRyZW46IG5vZGVzLnNsaWNlKGkwLCBpMSl9KTtcbiAgICBpZiAocm93LmRpY2UpIHRyZWVtYXBEaWNlKHJvdywgeDAsIHkwLCB4MSwgdmFsdWUgPyB5MCArPSBkeSAqIHN1bVZhbHVlIC8gdmFsdWUgOiB5MSk7XG4gICAgZWxzZSB0cmVlbWFwU2xpY2Uocm93LCB4MCwgeTAsIHZhbHVlID8geDAgKz0gZHggKiBzdW1WYWx1ZSAvIHZhbHVlIDogeDEsIHkxKTtcbiAgICB2YWx1ZSAtPSBzdW1WYWx1ZSwgaTAgPSBpMTtcbiAgfVxuXG4gIHJldHVybiByb3dzO1xufVxuXG52YXIgc3F1YXJpZnkgPSAoKGZ1bmN0aW9uIGN1c3RvbShyYXRpbykge1xuXG4gIGZ1bmN0aW9uIHNxdWFyaWZ5KHBhcmVudCwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgICBzcXVhcmlmeVJhdGlvKHJhdGlvLCBwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKTtcbiAgfVxuXG4gIHNxdWFyaWZ5LnJhdGlvID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBjdXN0b20oKHggPSAreCkgPiAxID8geCA6IDEpO1xuICB9O1xuXG4gIHJldHVybiBzcXVhcmlmeTtcbn0pKShwaGkpO1xuXG52YXIgaW5kZXgkMSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgdGlsZSA9IHNxdWFyaWZ5LFxuICAgICAgcm91bmQgPSBmYWxzZSxcbiAgICAgIGR4ID0gMSxcbiAgICAgIGR5ID0gMSxcbiAgICAgIHBhZGRpbmdTdGFjayA9IFswXSxcbiAgICAgIHBhZGRpbmdJbm5lciA9IGNvbnN0YW50WmVybyxcbiAgICAgIHBhZGRpbmdUb3AgPSBjb25zdGFudFplcm8sXG4gICAgICBwYWRkaW5nUmlnaHQgPSBjb25zdGFudFplcm8sXG4gICAgICBwYWRkaW5nQm90dG9tID0gY29uc3RhbnRaZXJvLFxuICAgICAgcGFkZGluZ0xlZnQgPSBjb25zdGFudFplcm87XG5cbiAgZnVuY3Rpb24gdHJlZW1hcChyb290KSB7XG4gICAgcm9vdC54MCA9XG4gICAgcm9vdC55MCA9IDA7XG4gICAgcm9vdC54MSA9IGR4O1xuICAgIHJvb3QueTEgPSBkeTtcbiAgICByb290LmVhY2hCZWZvcmUocG9zaXRpb25Ob2RlKTtcbiAgICBwYWRkaW5nU3RhY2sgPSBbMF07XG4gICAgaWYgKHJvdW5kKSByb290LmVhY2hCZWZvcmUocm91bmROb2RlKTtcbiAgICByZXR1cm4gcm9vdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBvc2l0aW9uTm9kZShub2RlKSB7XG4gICAgdmFyIHAgPSBwYWRkaW5nU3RhY2tbbm9kZS5kZXB0aF0sXG4gICAgICAgIHgwID0gbm9kZS54MCArIHAsXG4gICAgICAgIHkwID0gbm9kZS55MCArIHAsXG4gICAgICAgIHgxID0gbm9kZS54MSAtIHAsXG4gICAgICAgIHkxID0gbm9kZS55MSAtIHA7XG4gICAgaWYgKHgxIDwgeDApIHgwID0geDEgPSAoeDAgKyB4MSkgLyAyO1xuICAgIGlmICh5MSA8IHkwKSB5MCA9IHkxID0gKHkwICsgeTEpIC8gMjtcbiAgICBub2RlLngwID0geDA7XG4gICAgbm9kZS55MCA9IHkwO1xuICAgIG5vZGUueDEgPSB4MTtcbiAgICBub2RlLnkxID0geTE7XG4gICAgaWYgKG5vZGUuY2hpbGRyZW4pIHtcbiAgICAgIHAgPSBwYWRkaW5nU3RhY2tbbm9kZS5kZXB0aCArIDFdID0gcGFkZGluZ0lubmVyKG5vZGUpIC8gMjtcbiAgICAgIHgwICs9IHBhZGRpbmdMZWZ0KG5vZGUpIC0gcDtcbiAgICAgIHkwICs9IHBhZGRpbmdUb3Aobm9kZSkgLSBwO1xuICAgICAgeDEgLT0gcGFkZGluZ1JpZ2h0KG5vZGUpIC0gcDtcbiAgICAgIHkxIC09IHBhZGRpbmdCb3R0b20obm9kZSkgLSBwO1xuICAgICAgaWYgKHgxIDwgeDApIHgwID0geDEgPSAoeDAgKyB4MSkgLyAyO1xuICAgICAgaWYgKHkxIDwgeTApIHkwID0geTEgPSAoeTAgKyB5MSkgLyAyO1xuICAgICAgdGlsZShub2RlLCB4MCwgeTAsIHgxLCB5MSk7XG4gICAgfVxuICB9XG5cbiAgdHJlZW1hcC5yb3VuZCA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyb3VuZCA9ICEheCwgdHJlZW1hcCkgOiByb3VuZDtcbiAgfTtcblxuICB0cmVlbWFwLnNpemUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZHggPSAreFswXSwgZHkgPSAreFsxXSwgdHJlZW1hcCkgOiBbZHgsIGR5XTtcbiAgfTtcblxuICB0cmVlbWFwLnRpbGUgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodGlsZSA9IHJlcXVpcmVkKHgpLCB0cmVlbWFwKSA6IHRpbGU7XG4gIH07XG5cbiAgdHJlZW1hcC5wYWRkaW5nID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gdHJlZW1hcC5wYWRkaW5nSW5uZXIoeCkucGFkZGluZ091dGVyKHgpIDogdHJlZW1hcC5wYWRkaW5nSW5uZXIoKTtcbiAgfTtcblxuICB0cmVlbWFwLnBhZGRpbmdJbm5lciA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYWRkaW5nSW5uZXIgPSB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geCA6IGNvbnN0YW50KCt4KSwgdHJlZW1hcCkgOiBwYWRkaW5nSW5uZXI7XG4gIH07XG5cbiAgdHJlZW1hcC5wYWRkaW5nT3V0ZXIgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyB0cmVlbWFwLnBhZGRpbmdUb3AoeCkucGFkZGluZ1JpZ2h0KHgpLnBhZGRpbmdCb3R0b20oeCkucGFkZGluZ0xlZnQoeCkgOiB0cmVlbWFwLnBhZGRpbmdUb3AoKTtcbiAgfTtcblxuICB0cmVlbWFwLnBhZGRpbmdUb3AgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkZGluZ1RvcCA9IHR5cGVvZiB4ID09PSBcImZ1bmN0aW9uXCIgPyB4IDogY29uc3RhbnQoK3gpLCB0cmVlbWFwKSA6IHBhZGRpbmdUb3A7XG4gIH07XG5cbiAgdHJlZW1hcC5wYWRkaW5nUmlnaHQgPSBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkZGluZ1JpZ2h0ID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBjb25zdGFudCgreCksIHRyZWVtYXApIDogcGFkZGluZ1JpZ2h0O1xuICB9O1xuXG4gIHRyZWVtYXAucGFkZGluZ0JvdHRvbSA9IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYWRkaW5nQm90dG9tID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBjb25zdGFudCgreCksIHRyZWVtYXApIDogcGFkZGluZ0JvdHRvbTtcbiAgfTtcblxuICB0cmVlbWFwLnBhZGRpbmdMZWZ0ID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBhZGRpbmdMZWZ0ID0gdHlwZW9mIHggPT09IFwiZnVuY3Rpb25cIiA/IHggOiBjb25zdGFudCgreCksIHRyZWVtYXApIDogcGFkZGluZ0xlZnQ7XG4gIH07XG5cbiAgcmV0dXJuIHRyZWVtYXA7XG59O1xuXG52YXIgYmluYXJ5ID0gZnVuY3Rpb24ocGFyZW50LCB4MCwgeTAsIHgxLCB5MSkge1xuICB2YXIgbm9kZXMgPSBwYXJlbnQuY2hpbGRyZW4sXG4gICAgICBpLCBuID0gbm9kZXMubGVuZ3RoLFxuICAgICAgc3VtLCBzdW1zID0gbmV3IEFycmF5KG4gKyAxKTtcblxuICBmb3IgKHN1bXNbMF0gPSBzdW0gPSBpID0gMDsgaSA8IG47ICsraSkge1xuICAgIHN1bXNbaSArIDFdID0gc3VtICs9IG5vZGVzW2ldLnZhbHVlO1xuICB9XG5cbiAgcGFydGl0aW9uKDAsIG4sIHBhcmVudC52YWx1ZSwgeDAsIHkwLCB4MSwgeTEpO1xuXG4gIGZ1bmN0aW9uIHBhcnRpdGlvbihpLCBqLCB2YWx1ZSwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgICBpZiAoaSA+PSBqIC0gMSkge1xuICAgICAgdmFyIG5vZGUgPSBub2Rlc1tpXTtcbiAgICAgIG5vZGUueDAgPSB4MCwgbm9kZS55MCA9IHkwO1xuICAgICAgbm9kZS54MSA9IHgxLCBub2RlLnkxID0geTE7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHZhbHVlT2Zmc2V0ID0gc3Vtc1tpXSxcbiAgICAgICAgdmFsdWVUYXJnZXQgPSAodmFsdWUgLyAyKSArIHZhbHVlT2Zmc2V0LFxuICAgICAgICBrID0gaSArIDEsXG4gICAgICAgIGhpID0gaiAtIDE7XG5cbiAgICB3aGlsZSAoayA8IGhpKSB7XG4gICAgICB2YXIgbWlkID0gayArIGhpID4+PiAxO1xuICAgICAgaWYgKHN1bXNbbWlkXSA8IHZhbHVlVGFyZ2V0KSBrID0gbWlkICsgMTtcbiAgICAgIGVsc2UgaGkgPSBtaWQ7XG4gICAgfVxuXG4gICAgaWYgKCh2YWx1ZVRhcmdldCAtIHN1bXNbayAtIDFdKSA8IChzdW1zW2tdIC0gdmFsdWVUYXJnZXQpICYmIGkgKyAxIDwgaykgLS1rO1xuXG4gICAgdmFyIHZhbHVlTGVmdCA9IHN1bXNba10gLSB2YWx1ZU9mZnNldCxcbiAgICAgICAgdmFsdWVSaWdodCA9IHZhbHVlIC0gdmFsdWVMZWZ0O1xuXG4gICAgaWYgKCh4MSAtIHgwKSA+ICh5MSAtIHkwKSkge1xuICAgICAgdmFyIHhrID0gKHgwICogdmFsdWVSaWdodCArIHgxICogdmFsdWVMZWZ0KSAvIHZhbHVlO1xuICAgICAgcGFydGl0aW9uKGksIGssIHZhbHVlTGVmdCwgeDAsIHkwLCB4aywgeTEpO1xuICAgICAgcGFydGl0aW9uKGssIGosIHZhbHVlUmlnaHQsIHhrLCB5MCwgeDEsIHkxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHlrID0gKHkwICogdmFsdWVSaWdodCArIHkxICogdmFsdWVMZWZ0KSAvIHZhbHVlO1xuICAgICAgcGFydGl0aW9uKGksIGssIHZhbHVlTGVmdCwgeDAsIHkwLCB4MSwgeWspO1xuICAgICAgcGFydGl0aW9uKGssIGosIHZhbHVlUmlnaHQsIHgwLCB5aywgeDEsIHkxKTtcbiAgICB9XG4gIH1cbn07XG5cbnZhciBzbGljZURpY2UgPSBmdW5jdGlvbihwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gIChwYXJlbnQuZGVwdGggJiAxID8gdHJlZW1hcFNsaWNlIDogdHJlZW1hcERpY2UpKHBhcmVudCwgeDAsIHkwLCB4MSwgeTEpO1xufTtcblxudmFyIHJlc3F1YXJpZnkgPSAoKGZ1bmN0aW9uIGN1c3RvbShyYXRpbykge1xuXG4gIGZ1bmN0aW9uIHJlc3F1YXJpZnkocGFyZW50LCB4MCwgeTAsIHgxLCB5MSkge1xuICAgIGlmICgocm93cyA9IHBhcmVudC5fc3F1YXJpZnkpICYmIChyb3dzLnJhdGlvID09PSByYXRpbykpIHtcbiAgICAgIHZhciByb3dzLFxuICAgICAgICAgIHJvdyxcbiAgICAgICAgICBub2RlcyxcbiAgICAgICAgICBpLFxuICAgICAgICAgIGogPSAtMSxcbiAgICAgICAgICBuLFxuICAgICAgICAgIG0gPSByb3dzLmxlbmd0aCxcbiAgICAgICAgICB2YWx1ZSA9IHBhcmVudC52YWx1ZTtcblxuICAgICAgd2hpbGUgKCsraiA8IG0pIHtcbiAgICAgICAgcm93ID0gcm93c1tqXSwgbm9kZXMgPSByb3cuY2hpbGRyZW47XG4gICAgICAgIGZvciAoaSA9IHJvdy52YWx1ZSA9IDAsIG4gPSBub2Rlcy5sZW5ndGg7IGkgPCBuOyArK2kpIHJvdy52YWx1ZSArPSBub2Rlc1tpXS52YWx1ZTtcbiAgICAgICAgaWYgKHJvdy5kaWNlKSB0cmVlbWFwRGljZShyb3csIHgwLCB5MCwgeDEsIHkwICs9ICh5MSAtIHkwKSAqIHJvdy52YWx1ZSAvIHZhbHVlKTtcbiAgICAgICAgZWxzZSB0cmVlbWFwU2xpY2Uocm93LCB4MCwgeTAsIHgwICs9ICh4MSAtIHgwKSAqIHJvdy52YWx1ZSAvIHZhbHVlLCB5MSk7XG4gICAgICAgIHZhbHVlIC09IHJvdy52YWx1ZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcGFyZW50Ll9zcXVhcmlmeSA9IHJvd3MgPSBzcXVhcmlmeVJhdGlvKHJhdGlvLCBwYXJlbnQsIHgwLCB5MCwgeDEsIHkxKTtcbiAgICAgIHJvd3MucmF0aW8gPSByYXRpbztcbiAgICB9XG4gIH1cblxuICByZXNxdWFyaWZ5LnJhdGlvID0gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiBjdXN0b20oKHggPSAreCkgPiAxID8geCA6IDEpO1xuICB9O1xuXG4gIHJldHVybiByZXNxdWFyaWZ5O1xufSkpKHBoaSk7XG5cbmV4cG9ydHMuY2x1c3RlciA9IGNsdXN0ZXI7XG5leHBvcnRzLmhpZXJhcmNoeSA9IGhpZXJhcmNoeTtcbmV4cG9ydHMucGFjayA9IGluZGV4O1xuZXhwb3J0cy5wYWNrU2libGluZ3MgPSBzaWJsaW5ncztcbmV4cG9ydHMucGFja0VuY2xvc2UgPSBlbmNsb3NlO1xuZXhwb3J0cy5wYXJ0aXRpb24gPSBwYXJ0aXRpb247XG5leHBvcnRzLnN0cmF0aWZ5ID0gc3RyYXRpZnk7XG5leHBvcnRzLnRyZWUgPSB0cmVlO1xuZXhwb3J0cy50cmVlbWFwID0gaW5kZXgkMTtcbmV4cG9ydHMudHJlZW1hcEJpbmFyeSA9IGJpbmFyeTtcbmV4cG9ydHMudHJlZW1hcERpY2UgPSB0cmVlbWFwRGljZTtcbmV4cG9ydHMudHJlZW1hcFNsaWNlID0gdHJlZW1hcFNsaWNlO1xuZXhwb3J0cy50cmVlbWFwU2xpY2VEaWNlID0gc2xpY2VEaWNlO1xuZXhwb3J0cy50cmVlbWFwU3F1YXJpZnkgPSBzcXVhcmlmeTtcbmV4cG9ydHMudHJlZW1hcFJlc3F1YXJpZnkgPSByZXNxdWFyaWZ5O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1pbnRlcnBvbGF0ZS8gVmVyc2lvbiAxLjEuNi4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzLCByZXF1aXJlKCdkMy1jb2xvcicpKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtY29sb3InXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLGQzQ29sb3IpIHsgJ3VzZSBzdHJpY3QnO1xuXG5mdW5jdGlvbiBiYXNpcyh0MSwgdjAsIHYxLCB2MiwgdjMpIHtcbiAgdmFyIHQyID0gdDEgKiB0MSwgdDMgPSB0MiAqIHQxO1xuICByZXR1cm4gKCgxIC0gMyAqIHQxICsgMyAqIHQyIC0gdDMpICogdjBcbiAgICAgICsgKDQgLSA2ICogdDIgKyAzICogdDMpICogdjFcbiAgICAgICsgKDEgKyAzICogdDEgKyAzICogdDIgLSAzICogdDMpICogdjJcbiAgICAgICsgdDMgKiB2MykgLyA2O1xufVxuXG52YXIgYmFzaXMkMSA9IGZ1bmN0aW9uKHZhbHVlcykge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGggLSAxO1xuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIHZhciBpID0gdCA8PSAwID8gKHQgPSAwKSA6IHQgPj0gMSA/ICh0ID0gMSwgbiAtIDEpIDogTWF0aC5mbG9vcih0ICogbiksXG4gICAgICAgIHYxID0gdmFsdWVzW2ldLFxuICAgICAgICB2MiA9IHZhbHVlc1tpICsgMV0sXG4gICAgICAgIHYwID0gaSA+IDAgPyB2YWx1ZXNbaSAtIDFdIDogMiAqIHYxIC0gdjIsXG4gICAgICAgIHYzID0gaSA8IG4gLSAxID8gdmFsdWVzW2kgKyAyXSA6IDIgKiB2MiAtIHYxO1xuICAgIHJldHVybiBiYXNpcygodCAtIGkgLyBuKSAqIG4sIHYwLCB2MSwgdjIsIHYzKTtcbiAgfTtcbn07XG5cbnZhciBiYXNpc0Nsb3NlZCA9IGZ1bmN0aW9uKHZhbHVlcykge1xuICB2YXIgbiA9IHZhbHVlcy5sZW5ndGg7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgdmFyIGkgPSBNYXRoLmZsb29yKCgodCAlPSAxKSA8IDAgPyArK3QgOiB0KSAqIG4pLFxuICAgICAgICB2MCA9IHZhbHVlc1soaSArIG4gLSAxKSAlIG5dLFxuICAgICAgICB2MSA9IHZhbHVlc1tpICUgbl0sXG4gICAgICAgIHYyID0gdmFsdWVzWyhpICsgMSkgJSBuXSxcbiAgICAgICAgdjMgPSB2YWx1ZXNbKGkgKyAyKSAlIG5dO1xuICAgIHJldHVybiBiYXNpcygodCAtIGkgLyBuKSAqIG4sIHYwLCB2MSwgdjIsIHYzKTtcbiAgfTtcbn07XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxuZnVuY3Rpb24gbGluZWFyKGEsIGQpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gYSArIHQgKiBkO1xuICB9O1xufVxuXG5mdW5jdGlvbiBleHBvbmVudGlhbChhLCBiLCB5KSB7XG4gIHJldHVybiBhID0gTWF0aC5wb3coYSwgeSksIGIgPSBNYXRoLnBvdyhiLCB5KSAtIGEsIHkgPSAxIC8geSwgZnVuY3Rpb24odCkge1xuICAgIHJldHVybiBNYXRoLnBvdyhhICsgdCAqIGIsIHkpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBodWUoYSwgYikge1xuICB2YXIgZCA9IGIgLSBhO1xuICByZXR1cm4gZCA/IGxpbmVhcihhLCBkID4gMTgwIHx8IGQgPCAtMTgwID8gZCAtIDM2MCAqIE1hdGgucm91bmQoZCAvIDM2MCkgOiBkKSA6IGNvbnN0YW50KGlzTmFOKGEpID8gYiA6IGEpO1xufVxuXG5mdW5jdGlvbiBnYW1tYSh5KSB7XG4gIHJldHVybiAoeSA9ICt5KSA9PT0gMSA/IG5vZ2FtbWEgOiBmdW5jdGlvbihhLCBiKSB7XG4gICAgcmV0dXJuIGIgLSBhID8gZXhwb25lbnRpYWwoYSwgYiwgeSkgOiBjb25zdGFudChpc05hTihhKSA/IGIgOiBhKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbm9nYW1tYShhLCBiKSB7XG4gIHZhciBkID0gYiAtIGE7XG4gIHJldHVybiBkID8gbGluZWFyKGEsIGQpIDogY29uc3RhbnQoaXNOYU4oYSkgPyBiIDogYSk7XG59XG5cbnZhciByZ2IkMSA9ICgoZnVuY3Rpb24gcmdiR2FtbWEoeSkge1xuICB2YXIgY29sb3IkJDEgPSBnYW1tYSh5KTtcblxuICBmdW5jdGlvbiByZ2IkJDEoc3RhcnQsIGVuZCkge1xuICAgIHZhciByID0gY29sb3IkJDEoKHN0YXJ0ID0gZDNDb2xvci5yZ2Ioc3RhcnQpKS5yLCAoZW5kID0gZDNDb2xvci5yZ2IoZW5kKSkuciksXG4gICAgICAgIGcgPSBjb2xvciQkMShzdGFydC5nLCBlbmQuZyksXG4gICAgICAgIGIgPSBjb2xvciQkMShzdGFydC5iLCBlbmQuYiksXG4gICAgICAgIG9wYWNpdHkgPSBub2dhbW1hKHN0YXJ0Lm9wYWNpdHksIGVuZC5vcGFjaXR5KTtcbiAgICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgICAgc3RhcnQuciA9IHIodCk7XG4gICAgICBzdGFydC5nID0gZyh0KTtcbiAgICAgIHN0YXJ0LmIgPSBiKHQpO1xuICAgICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgICByZXR1cm4gc3RhcnQgKyBcIlwiO1xuICAgIH07XG4gIH1cblxuICByZ2IkJDEuZ2FtbWEgPSByZ2JHYW1tYTtcblxuICByZXR1cm4gcmdiJCQxO1xufSkpKDEpO1xuXG5mdW5jdGlvbiByZ2JTcGxpbmUoc3BsaW5lKSB7XG4gIHJldHVybiBmdW5jdGlvbihjb2xvcnMpIHtcbiAgICB2YXIgbiA9IGNvbG9ycy5sZW5ndGgsXG4gICAgICAgIHIgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGcgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGIgPSBuZXcgQXJyYXkobiksXG4gICAgICAgIGksIGNvbG9yJCQxO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGNvbG9yJCQxID0gZDNDb2xvci5yZ2IoY29sb3JzW2ldKTtcbiAgICAgIHJbaV0gPSBjb2xvciQkMS5yIHx8IDA7XG4gICAgICBnW2ldID0gY29sb3IkJDEuZyB8fCAwO1xuICAgICAgYltpXSA9IGNvbG9yJCQxLmIgfHwgMDtcbiAgICB9XG4gICAgciA9IHNwbGluZShyKTtcbiAgICBnID0gc3BsaW5lKGcpO1xuICAgIGIgPSBzcGxpbmUoYik7XG4gICAgY29sb3IkJDEub3BhY2l0eSA9IDE7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIGNvbG9yJCQxLnIgPSByKHQpO1xuICAgICAgY29sb3IkJDEuZyA9IGcodCk7XG4gICAgICBjb2xvciQkMS5iID0gYih0KTtcbiAgICAgIHJldHVybiBjb2xvciQkMSArIFwiXCI7XG4gICAgfTtcbiAgfTtcbn1cblxudmFyIHJnYkJhc2lzID0gcmdiU3BsaW5lKGJhc2lzJDEpO1xudmFyIHJnYkJhc2lzQ2xvc2VkID0gcmdiU3BsaW5lKGJhc2lzQ2xvc2VkKTtcblxudmFyIGFycmF5ID0gZnVuY3Rpb24oYSwgYikge1xuICB2YXIgbmIgPSBiID8gYi5sZW5ndGggOiAwLFxuICAgICAgbmEgPSBhID8gTWF0aC5taW4obmIsIGEubGVuZ3RoKSA6IDAsXG4gICAgICB4ID0gbmV3IEFycmF5KG5hKSxcbiAgICAgIGMgPSBuZXcgQXJyYXkobmIpLFxuICAgICAgaTtcblxuICBmb3IgKGkgPSAwOyBpIDwgbmE7ICsraSkgeFtpXSA9IHZhbHVlKGFbaV0sIGJbaV0pO1xuICBmb3IgKDsgaSA8IG5iOyArK2kpIGNbaV0gPSBiW2ldO1xuXG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgZm9yIChpID0gMDsgaSA8IG5hOyArK2kpIGNbaV0gPSB4W2ldKHQpO1xuICAgIHJldHVybiBjO1xuICB9O1xufTtcblxudmFyIGRhdGUgPSBmdW5jdGlvbihhLCBiKSB7XG4gIHZhciBkID0gbmV3IERhdGU7XG4gIHJldHVybiBhID0gK2EsIGIgLT0gYSwgZnVuY3Rpb24odCkge1xuICAgIHJldHVybiBkLnNldFRpbWUoYSArIGIgKiB0KSwgZDtcbiAgfTtcbn07XG5cbnZhciBudW1iZXIgPSBmdW5jdGlvbihhLCBiKSB7XG4gIHJldHVybiBhID0gK2EsIGIgLT0gYSwgZnVuY3Rpb24odCkge1xuICAgIHJldHVybiBhICsgYiAqIHQ7XG4gIH07XG59O1xuXG52YXIgb2JqZWN0ID0gZnVuY3Rpb24oYSwgYikge1xuICB2YXIgaSA9IHt9LFxuICAgICAgYyA9IHt9LFxuICAgICAgaztcblxuICBpZiAoYSA9PT0gbnVsbCB8fCB0eXBlb2YgYSAhPT0gXCJvYmplY3RcIikgYSA9IHt9O1xuICBpZiAoYiA9PT0gbnVsbCB8fCB0eXBlb2YgYiAhPT0gXCJvYmplY3RcIikgYiA9IHt9O1xuXG4gIGZvciAoayBpbiBiKSB7XG4gICAgaWYgKGsgaW4gYSkge1xuICAgICAgaVtrXSA9IHZhbHVlKGFba10sIGJba10pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjW2tdID0gYltrXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24odCkge1xuICAgIGZvciAoayBpbiBpKSBjW2tdID0gaVtrXSh0KTtcbiAgICByZXR1cm4gYztcbiAgfTtcbn07XG5cbnZhciByZUEgPSAvWy0rXT8oPzpcXGQrXFwuP1xcZCp8XFwuP1xcZCspKD86W2VFXVstK10/XFxkKyk/L2c7XG52YXIgcmVCID0gbmV3IFJlZ0V4cChyZUEuc291cmNlLCBcImdcIik7XG5cbmZ1bmN0aW9uIHplcm8oYikge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGI7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG9uZShiKSB7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgcmV0dXJuIGIodCkgKyBcIlwiO1xuICB9O1xufVxuXG52YXIgc3RyaW5nID0gZnVuY3Rpb24oYSwgYikge1xuICB2YXIgYmkgPSByZUEubGFzdEluZGV4ID0gcmVCLmxhc3RJbmRleCA9IDAsIC8vIHNjYW4gaW5kZXggZm9yIG5leHQgbnVtYmVyIGluIGJcbiAgICAgIGFtLCAvLyBjdXJyZW50IG1hdGNoIGluIGFcbiAgICAgIGJtLCAvLyBjdXJyZW50IG1hdGNoIGluIGJcbiAgICAgIGJzLCAvLyBzdHJpbmcgcHJlY2VkaW5nIGN1cnJlbnQgbnVtYmVyIGluIGIsIGlmIGFueVxuICAgICAgaSA9IC0xLCAvLyBpbmRleCBpbiBzXG4gICAgICBzID0gW10sIC8vIHN0cmluZyBjb25zdGFudHMgYW5kIHBsYWNlaG9sZGVyc1xuICAgICAgcSA9IFtdOyAvLyBudW1iZXIgaW50ZXJwb2xhdG9yc1xuXG4gIC8vIENvZXJjZSBpbnB1dHMgdG8gc3RyaW5ncy5cbiAgYSA9IGEgKyBcIlwiLCBiID0gYiArIFwiXCI7XG5cbiAgLy8gSW50ZXJwb2xhdGUgcGFpcnMgb2YgbnVtYmVycyBpbiBhICYgYi5cbiAgd2hpbGUgKChhbSA9IHJlQS5leGVjKGEpKVxuICAgICAgJiYgKGJtID0gcmVCLmV4ZWMoYikpKSB7XG4gICAgaWYgKChicyA9IGJtLmluZGV4KSA+IGJpKSB7IC8vIGEgc3RyaW5nIHByZWNlZGVzIHRoZSBuZXh0IG51bWJlciBpbiBiXG4gICAgICBicyA9IGIuc2xpY2UoYmksIGJzKTtcbiAgICAgIGlmIChzW2ldKSBzW2ldICs9IGJzOyAvLyBjb2FsZXNjZSB3aXRoIHByZXZpb3VzIHN0cmluZ1xuICAgICAgZWxzZSBzWysraV0gPSBicztcbiAgICB9XG4gICAgaWYgKChhbSA9IGFtWzBdKSA9PT0gKGJtID0gYm1bMF0pKSB7IC8vIG51bWJlcnMgaW4gYSAmIGIgbWF0Y2hcbiAgICAgIGlmIChzW2ldKSBzW2ldICs9IGJtOyAvLyBjb2FsZXNjZSB3aXRoIHByZXZpb3VzIHN0cmluZ1xuICAgICAgZWxzZSBzWysraV0gPSBibTtcbiAgICB9IGVsc2UgeyAvLyBpbnRlcnBvbGF0ZSBub24tbWF0Y2hpbmcgbnVtYmVyc1xuICAgICAgc1srK2ldID0gbnVsbDtcbiAgICAgIHEucHVzaCh7aTogaSwgeDogbnVtYmVyKGFtLCBibSl9KTtcbiAgICB9XG4gICAgYmkgPSByZUIubGFzdEluZGV4O1xuICB9XG5cbiAgLy8gQWRkIHJlbWFpbnMgb2YgYi5cbiAgaWYgKGJpIDwgYi5sZW5ndGgpIHtcbiAgICBicyA9IGIuc2xpY2UoYmkpO1xuICAgIGlmIChzW2ldKSBzW2ldICs9IGJzOyAvLyBjb2FsZXNjZSB3aXRoIHByZXZpb3VzIHN0cmluZ1xuICAgIGVsc2Ugc1srK2ldID0gYnM7XG4gIH1cblxuICAvLyBTcGVjaWFsIG9wdGltaXphdGlvbiBmb3Igb25seSBhIHNpbmdsZSBtYXRjaC5cbiAgLy8gT3RoZXJ3aXNlLCBpbnRlcnBvbGF0ZSBlYWNoIG9mIHRoZSBudW1iZXJzIGFuZCByZWpvaW4gdGhlIHN0cmluZy5cbiAgcmV0dXJuIHMubGVuZ3RoIDwgMiA/IChxWzBdXG4gICAgICA/IG9uZShxWzBdLngpXG4gICAgICA6IHplcm8oYikpXG4gICAgICA6IChiID0gcS5sZW5ndGgsIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbzsgaSA8IGI7ICsraSkgc1sobyA9IHFbaV0pLmldID0gby54KHQpO1xuICAgICAgICAgIHJldHVybiBzLmpvaW4oXCJcIik7XG4gICAgICAgIH0pO1xufTtcblxudmFyIHZhbHVlID0gZnVuY3Rpb24oYSwgYikge1xuICB2YXIgdCA9IHR5cGVvZiBiLCBjO1xuICByZXR1cm4gYiA9PSBudWxsIHx8IHQgPT09IFwiYm9vbGVhblwiID8gY29uc3RhbnQoYilcbiAgICAgIDogKHQgPT09IFwibnVtYmVyXCIgPyBudW1iZXJcbiAgICAgIDogdCA9PT0gXCJzdHJpbmdcIiA/ICgoYyA9IGQzQ29sb3IuY29sb3IoYikpID8gKGIgPSBjLCByZ2IkMSkgOiBzdHJpbmcpXG4gICAgICA6IGIgaW5zdGFuY2VvZiBkM0NvbG9yLmNvbG9yID8gcmdiJDFcbiAgICAgIDogYiBpbnN0YW5jZW9mIERhdGUgPyBkYXRlXG4gICAgICA6IEFycmF5LmlzQXJyYXkoYikgPyBhcnJheVxuICAgICAgOiB0eXBlb2YgYi52YWx1ZU9mICE9PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGIudG9TdHJpbmcgIT09IFwiZnVuY3Rpb25cIiB8fCBpc05hTihiKSA/IG9iamVjdFxuICAgICAgOiBudW1iZXIpKGEsIGIpO1xufTtcblxudmFyIHJvdW5kID0gZnVuY3Rpb24oYSwgYikge1xuICByZXR1cm4gYSA9ICthLCBiIC09IGEsIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChhICsgYiAqIHQpO1xuICB9O1xufTtcblxudmFyIGRlZ3JlZXMgPSAxODAgLyBNYXRoLlBJO1xuXG52YXIgaWRlbnRpdHkgPSB7XG4gIHRyYW5zbGF0ZVg6IDAsXG4gIHRyYW5zbGF0ZVk6IDAsXG4gIHJvdGF0ZTogMCxcbiAgc2tld1g6IDAsXG4gIHNjYWxlWDogMSxcbiAgc2NhbGVZOiAxXG59O1xuXG52YXIgZGVjb21wb3NlID0gZnVuY3Rpb24oYSwgYiwgYywgZCwgZSwgZikge1xuICB2YXIgc2NhbGVYLCBzY2FsZVksIHNrZXdYO1xuICBpZiAoc2NhbGVYID0gTWF0aC5zcXJ0KGEgKiBhICsgYiAqIGIpKSBhIC89IHNjYWxlWCwgYiAvPSBzY2FsZVg7XG4gIGlmIChza2V3WCA9IGEgKiBjICsgYiAqIGQpIGMgLT0gYSAqIHNrZXdYLCBkIC09IGIgKiBza2V3WDtcbiAgaWYgKHNjYWxlWSA9IE1hdGguc3FydChjICogYyArIGQgKiBkKSkgYyAvPSBzY2FsZVksIGQgLz0gc2NhbGVZLCBza2V3WCAvPSBzY2FsZVk7XG4gIGlmIChhICogZCA8IGIgKiBjKSBhID0gLWEsIGIgPSAtYiwgc2tld1ggPSAtc2tld1gsIHNjYWxlWCA9IC1zY2FsZVg7XG4gIHJldHVybiB7XG4gICAgdHJhbnNsYXRlWDogZSxcbiAgICB0cmFuc2xhdGVZOiBmLFxuICAgIHJvdGF0ZTogTWF0aC5hdGFuMihiLCBhKSAqIGRlZ3JlZXMsXG4gICAgc2tld1g6IE1hdGguYXRhbihza2V3WCkgKiBkZWdyZWVzLFxuICAgIHNjYWxlWDogc2NhbGVYLFxuICAgIHNjYWxlWTogc2NhbGVZXG4gIH07XG59O1xuXG52YXIgY3NzTm9kZTtcbnZhciBjc3NSb290O1xudmFyIGNzc1ZpZXc7XG52YXIgc3ZnTm9kZTtcblxuZnVuY3Rpb24gcGFyc2VDc3ModmFsdWUpIHtcbiAgaWYgKHZhbHVlID09PSBcIm5vbmVcIikgcmV0dXJuIGlkZW50aXR5O1xuICBpZiAoIWNzc05vZGUpIGNzc05vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiRElWXCIpLCBjc3NSb290ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCBjc3NWaWV3ID0gZG9jdW1lbnQuZGVmYXVsdFZpZXc7XG4gIGNzc05vZGUuc3R5bGUudHJhbnNmb3JtID0gdmFsdWU7XG4gIHZhbHVlID0gY3NzVmlldy5nZXRDb21wdXRlZFN0eWxlKGNzc1Jvb3QuYXBwZW5kQ2hpbGQoY3NzTm9kZSksIG51bGwpLmdldFByb3BlcnR5VmFsdWUoXCJ0cmFuc2Zvcm1cIik7XG4gIGNzc1Jvb3QucmVtb3ZlQ2hpbGQoY3NzTm9kZSk7XG4gIHZhbHVlID0gdmFsdWUuc2xpY2UoNywgLTEpLnNwbGl0KFwiLFwiKTtcbiAgcmV0dXJuIGRlY29tcG9zZSgrdmFsdWVbMF0sICt2YWx1ZVsxXSwgK3ZhbHVlWzJdLCArdmFsdWVbM10sICt2YWx1ZVs0XSwgK3ZhbHVlWzVdKTtcbn1cblxuZnVuY3Rpb24gcGFyc2VTdmcodmFsdWUpIHtcbiAgaWYgKHZhbHVlID09IG51bGwpIHJldHVybiBpZGVudGl0eTtcbiAgaWYgKCFzdmdOb2RlKSBzdmdOb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiwgXCJnXCIpO1xuICBzdmdOb2RlLnNldEF0dHJpYnV0ZShcInRyYW5zZm9ybVwiLCB2YWx1ZSk7XG4gIGlmICghKHZhbHVlID0gc3ZnTm9kZS50cmFuc2Zvcm0uYmFzZVZhbC5jb25zb2xpZGF0ZSgpKSkgcmV0dXJuIGlkZW50aXR5O1xuICB2YWx1ZSA9IHZhbHVlLm1hdHJpeDtcbiAgcmV0dXJuIGRlY29tcG9zZSh2YWx1ZS5hLCB2YWx1ZS5iLCB2YWx1ZS5jLCB2YWx1ZS5kLCB2YWx1ZS5lLCB2YWx1ZS5mKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJwb2xhdGVUcmFuc2Zvcm0ocGFyc2UsIHB4Q29tbWEsIHB4UGFyZW4sIGRlZ1BhcmVuKSB7XG5cbiAgZnVuY3Rpb24gcG9wKHMpIHtcbiAgICByZXR1cm4gcy5sZW5ndGggPyBzLnBvcCgpICsgXCIgXCIgOiBcIlwiO1xuICB9XG5cbiAgZnVuY3Rpb24gdHJhbnNsYXRlKHhhLCB5YSwgeGIsIHliLCBzLCBxKSB7XG4gICAgaWYgKHhhICE9PSB4YiB8fCB5YSAhPT0geWIpIHtcbiAgICAgIHZhciBpID0gcy5wdXNoKFwidHJhbnNsYXRlKFwiLCBudWxsLCBweENvbW1hLCBudWxsLCBweFBhcmVuKTtcbiAgICAgIHEucHVzaCh7aTogaSAtIDQsIHg6IG51bWJlcih4YSwgeGIpfSwge2k6IGkgLSAyLCB4OiBudW1iZXIoeWEsIHliKX0pO1xuICAgIH0gZWxzZSBpZiAoeGIgfHwgeWIpIHtcbiAgICAgIHMucHVzaChcInRyYW5zbGF0ZShcIiArIHhiICsgcHhDb21tYSArIHliICsgcHhQYXJlbik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcm90YXRlKGEsIGIsIHMsIHEpIHtcbiAgICBpZiAoYSAhPT0gYikge1xuICAgICAgaWYgKGEgLSBiID4gMTgwKSBiICs9IDM2MDsgZWxzZSBpZiAoYiAtIGEgPiAxODApIGEgKz0gMzYwOyAvLyBzaG9ydGVzdCBwYXRoXG4gICAgICBxLnB1c2goe2k6IHMucHVzaChwb3AocykgKyBcInJvdGF0ZShcIiwgbnVsbCwgZGVnUGFyZW4pIC0gMiwgeDogbnVtYmVyKGEsIGIpfSk7XG4gICAgfSBlbHNlIGlmIChiKSB7XG4gICAgICBzLnB1c2gocG9wKHMpICsgXCJyb3RhdGUoXCIgKyBiICsgZGVnUGFyZW4pO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHNrZXdYKGEsIGIsIHMsIHEpIHtcbiAgICBpZiAoYSAhPT0gYikge1xuICAgICAgcS5wdXNoKHtpOiBzLnB1c2gocG9wKHMpICsgXCJza2V3WChcIiwgbnVsbCwgZGVnUGFyZW4pIC0gMiwgeDogbnVtYmVyKGEsIGIpfSk7XG4gICAgfSBlbHNlIGlmIChiKSB7XG4gICAgICBzLnB1c2gocG9wKHMpICsgXCJza2V3WChcIiArIGIgKyBkZWdQYXJlbik7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2NhbGUoeGEsIHlhLCB4YiwgeWIsIHMsIHEpIHtcbiAgICBpZiAoeGEgIT09IHhiIHx8IHlhICE9PSB5Yikge1xuICAgICAgdmFyIGkgPSBzLnB1c2gocG9wKHMpICsgXCJzY2FsZShcIiwgbnVsbCwgXCIsXCIsIG51bGwsIFwiKVwiKTtcbiAgICAgIHEucHVzaCh7aTogaSAtIDQsIHg6IG51bWJlcih4YSwgeGIpfSwge2k6IGkgLSAyLCB4OiBudW1iZXIoeWEsIHliKX0pO1xuICAgIH0gZWxzZSBpZiAoeGIgIT09IDEgfHwgeWIgIT09IDEpIHtcbiAgICAgIHMucHVzaChwb3AocykgKyBcInNjYWxlKFwiICsgeGIgKyBcIixcIiArIHliICsgXCIpXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbihhLCBiKSB7XG4gICAgdmFyIHMgPSBbXSwgLy8gc3RyaW5nIGNvbnN0YW50cyBhbmQgcGxhY2Vob2xkZXJzXG4gICAgICAgIHEgPSBbXTsgLy8gbnVtYmVyIGludGVycG9sYXRvcnNcbiAgICBhID0gcGFyc2UoYSksIGIgPSBwYXJzZShiKTtcbiAgICB0cmFuc2xhdGUoYS50cmFuc2xhdGVYLCBhLnRyYW5zbGF0ZVksIGIudHJhbnNsYXRlWCwgYi50cmFuc2xhdGVZLCBzLCBxKTtcbiAgICByb3RhdGUoYS5yb3RhdGUsIGIucm90YXRlLCBzLCBxKTtcbiAgICBza2V3WChhLnNrZXdYLCBiLnNrZXdYLCBzLCBxKTtcbiAgICBzY2FsZShhLnNjYWxlWCwgYS5zY2FsZVksIGIuc2NhbGVYLCBiLnNjYWxlWSwgcywgcSk7XG4gICAgYSA9IGIgPSBudWxsOyAvLyBnY1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICB2YXIgaSA9IC0xLCBuID0gcS5sZW5ndGgsIG87XG4gICAgICB3aGlsZSAoKytpIDwgbikgc1sobyA9IHFbaV0pLmldID0gby54KHQpO1xuICAgICAgcmV0dXJuIHMuam9pbihcIlwiKTtcbiAgICB9O1xuICB9O1xufVxuXG52YXIgaW50ZXJwb2xhdGVUcmFuc2Zvcm1Dc3MgPSBpbnRlcnBvbGF0ZVRyYW5zZm9ybShwYXJzZUNzcywgXCJweCwgXCIsIFwicHgpXCIsIFwiZGVnKVwiKTtcbnZhciBpbnRlcnBvbGF0ZVRyYW5zZm9ybVN2ZyA9IGludGVycG9sYXRlVHJhbnNmb3JtKHBhcnNlU3ZnLCBcIiwgXCIsIFwiKVwiLCBcIilcIik7XG5cbnZhciByaG8gPSBNYXRoLlNRUlQyO1xudmFyIHJobzIgPSAyO1xudmFyIHJobzQgPSA0O1xudmFyIGVwc2lsb24yID0gMWUtMTI7XG5cbmZ1bmN0aW9uIGNvc2goeCkge1xuICByZXR1cm4gKCh4ID0gTWF0aC5leHAoeCkpICsgMSAvIHgpIC8gMjtcbn1cblxuZnVuY3Rpb24gc2luaCh4KSB7XG4gIHJldHVybiAoKHggPSBNYXRoLmV4cCh4KSkgLSAxIC8geCkgLyAyO1xufVxuXG5mdW5jdGlvbiB0YW5oKHgpIHtcbiAgcmV0dXJuICgoeCA9IE1hdGguZXhwKDIgKiB4KSkgLSAxKSAvICh4ICsgMSk7XG59XG5cbi8vIHAwID0gW3V4MCwgdXkwLCB3MF1cbi8vIHAxID0gW3V4MSwgdXkxLCB3MV1cbnZhciB6b29tID0gZnVuY3Rpb24ocDAsIHAxKSB7XG4gIHZhciB1eDAgPSBwMFswXSwgdXkwID0gcDBbMV0sIHcwID0gcDBbMl0sXG4gICAgICB1eDEgPSBwMVswXSwgdXkxID0gcDFbMV0sIHcxID0gcDFbMl0sXG4gICAgICBkeCA9IHV4MSAtIHV4MCxcbiAgICAgIGR5ID0gdXkxIC0gdXkwLFxuICAgICAgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeSxcbiAgICAgIGksXG4gICAgICBTO1xuXG4gIC8vIFNwZWNpYWwgY2FzZSBmb3IgdTAg4omFIHUxLlxuICBpZiAoZDIgPCBlcHNpbG9uMikge1xuICAgIFMgPSBNYXRoLmxvZyh3MSAvIHcwKSAvIHJobztcbiAgICBpID0gZnVuY3Rpb24odCkge1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgdXgwICsgdCAqIGR4LFxuICAgICAgICB1eTAgKyB0ICogZHksXG4gICAgICAgIHcwICogTWF0aC5leHAocmhvICogdCAqIFMpXG4gICAgICBdO1xuICAgIH07XG4gIH1cblxuICAvLyBHZW5lcmFsIGNhc2UuXG4gIGVsc2Uge1xuICAgIHZhciBkMSA9IE1hdGguc3FydChkMiksXG4gICAgICAgIGIwID0gKHcxICogdzEgLSB3MCAqIHcwICsgcmhvNCAqIGQyKSAvICgyICogdzAgKiByaG8yICogZDEpLFxuICAgICAgICBiMSA9ICh3MSAqIHcxIC0gdzAgKiB3MCAtIHJobzQgKiBkMikgLyAoMiAqIHcxICogcmhvMiAqIGQxKSxcbiAgICAgICAgcjAgPSBNYXRoLmxvZyhNYXRoLnNxcnQoYjAgKiBiMCArIDEpIC0gYjApLFxuICAgICAgICByMSA9IE1hdGgubG9nKE1hdGguc3FydChiMSAqIGIxICsgMSkgLSBiMSk7XG4gICAgUyA9IChyMSAtIHIwKSAvIHJobztcbiAgICBpID0gZnVuY3Rpb24odCkge1xuICAgICAgdmFyIHMgPSB0ICogUyxcbiAgICAgICAgICBjb3NocjAgPSBjb3NoKHIwKSxcbiAgICAgICAgICB1ID0gdzAgLyAocmhvMiAqIGQxKSAqIChjb3NocjAgKiB0YW5oKHJobyAqIHMgKyByMCkgLSBzaW5oKHIwKSk7XG4gICAgICByZXR1cm4gW1xuICAgICAgICB1eDAgKyB1ICogZHgsXG4gICAgICAgIHV5MCArIHUgKiBkeSxcbiAgICAgICAgdzAgKiBjb3NocjAgLyBjb3NoKHJobyAqIHMgKyByMClcbiAgICAgIF07XG4gICAgfTtcbiAgfVxuXG4gIGkuZHVyYXRpb24gPSBTICogMTAwMDtcblxuICByZXR1cm4gaTtcbn07XG5cbmZ1bmN0aW9uIGhzbCQxKGh1ZSQkMSkge1xuICByZXR1cm4gZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgIHZhciBoID0gaHVlJCQxKChzdGFydCA9IGQzQ29sb3IuaHNsKHN0YXJ0KSkuaCwgKGVuZCA9IGQzQ29sb3IuaHNsKGVuZCkpLmgpLFxuICAgICAgICBzID0gbm9nYW1tYShzdGFydC5zLCBlbmQucyksXG4gICAgICAgIGwgPSBub2dhbW1hKHN0YXJ0LmwsIGVuZC5sKSxcbiAgICAgICAgb3BhY2l0eSA9IG5vZ2FtbWEoc3RhcnQub3BhY2l0eSwgZW5kLm9wYWNpdHkpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgICBzdGFydC5oID0gaCh0KTtcbiAgICAgIHN0YXJ0LnMgPSBzKHQpO1xuICAgICAgc3RhcnQubCA9IGwodCk7XG4gICAgICBzdGFydC5vcGFjaXR5ID0gb3BhY2l0eSh0KTtcbiAgICAgIHJldHVybiBzdGFydCArIFwiXCI7XG4gICAgfTtcbiAgfVxufVxuXG52YXIgaHNsJDIgPSBoc2wkMShodWUpO1xudmFyIGhzbExvbmcgPSBoc2wkMShub2dhbW1hKTtcblxuZnVuY3Rpb24gbGFiJDEoc3RhcnQsIGVuZCkge1xuICB2YXIgbCA9IG5vZ2FtbWEoKHN0YXJ0ID0gZDNDb2xvci5sYWIoc3RhcnQpKS5sLCAoZW5kID0gZDNDb2xvci5sYWIoZW5kKSkubCksXG4gICAgICBhID0gbm9nYW1tYShzdGFydC5hLCBlbmQuYSksXG4gICAgICBiID0gbm9nYW1tYShzdGFydC5iLCBlbmQuYiksXG4gICAgICBvcGFjaXR5ID0gbm9nYW1tYShzdGFydC5vcGFjaXR5LCBlbmQub3BhY2l0eSk7XG4gIHJldHVybiBmdW5jdGlvbih0KSB7XG4gICAgc3RhcnQubCA9IGwodCk7XG4gICAgc3RhcnQuYSA9IGEodCk7XG4gICAgc3RhcnQuYiA9IGIodCk7XG4gICAgc3RhcnQub3BhY2l0eSA9IG9wYWNpdHkodCk7XG4gICAgcmV0dXJuIHN0YXJ0ICsgXCJcIjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gaGNsJDEoaHVlJCQxKSB7XG4gIHJldHVybiBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgdmFyIGggPSBodWUkJDEoKHN0YXJ0ID0gZDNDb2xvci5oY2woc3RhcnQpKS5oLCAoZW5kID0gZDNDb2xvci5oY2woZW5kKSkuaCksXG4gICAgICAgIGMgPSBub2dhbW1hKHN0YXJ0LmMsIGVuZC5jKSxcbiAgICAgICAgbCA9IG5vZ2FtbWEoc3RhcnQubCwgZW5kLmwpLFxuICAgICAgICBvcGFjaXR5ID0gbm9nYW1tYShzdGFydC5vcGFjaXR5LCBlbmQub3BhY2l0eSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgIHN0YXJ0LmggPSBoKHQpO1xuICAgICAgc3RhcnQuYyA9IGModCk7XG4gICAgICBzdGFydC5sID0gbCh0KTtcbiAgICAgIHN0YXJ0Lm9wYWNpdHkgPSBvcGFjaXR5KHQpO1xuICAgICAgcmV0dXJuIHN0YXJ0ICsgXCJcIjtcbiAgICB9O1xuICB9XG59XG5cbnZhciBoY2wkMiA9IGhjbCQxKGh1ZSk7XG52YXIgaGNsTG9uZyA9IGhjbCQxKG5vZ2FtbWEpO1xuXG5mdW5jdGlvbiBjdWJlaGVsaXgkMShodWUkJDEpIHtcbiAgcmV0dXJuIChmdW5jdGlvbiBjdWJlaGVsaXhHYW1tYSh5KSB7XG4gICAgeSA9ICt5O1xuXG4gICAgZnVuY3Rpb24gY3ViZWhlbGl4JCQxKHN0YXJ0LCBlbmQpIHtcbiAgICAgIHZhciBoID0gaHVlJCQxKChzdGFydCA9IGQzQ29sb3IuY3ViZWhlbGl4KHN0YXJ0KSkuaCwgKGVuZCA9IGQzQ29sb3IuY3ViZWhlbGl4KGVuZCkpLmgpLFxuICAgICAgICAgIHMgPSBub2dhbW1hKHN0YXJ0LnMsIGVuZC5zKSxcbiAgICAgICAgICBsID0gbm9nYW1tYShzdGFydC5sLCBlbmQubCksXG4gICAgICAgICAgb3BhY2l0eSA9IG5vZ2FtbWEoc3RhcnQub3BhY2l0eSwgZW5kLm9wYWNpdHkpO1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgc3RhcnQuaCA9IGgodCk7XG4gICAgICAgIHN0YXJ0LnMgPSBzKHQpO1xuICAgICAgICBzdGFydC5sID0gbChNYXRoLnBvdyh0LCB5KSk7XG4gICAgICAgIHN0YXJ0Lm9wYWNpdHkgPSBvcGFjaXR5KHQpO1xuICAgICAgICByZXR1cm4gc3RhcnQgKyBcIlwiO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBjdWJlaGVsaXgkJDEuZ2FtbWEgPSBjdWJlaGVsaXhHYW1tYTtcblxuICAgIHJldHVybiBjdWJlaGVsaXgkJDE7XG4gIH0pKDEpO1xufVxuXG52YXIgY3ViZWhlbGl4JDIgPSBjdWJlaGVsaXgkMShodWUpO1xudmFyIGN1YmVoZWxpeExvbmcgPSBjdWJlaGVsaXgkMShub2dhbW1hKTtcblxudmFyIHF1YW50aXplID0gZnVuY3Rpb24oaW50ZXJwb2xhdG9yLCBuKSB7XG4gIHZhciBzYW1wbGVzID0gbmV3IEFycmF5KG4pO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkgc2FtcGxlc1tpXSA9IGludGVycG9sYXRvcihpIC8gKG4gLSAxKSk7XG4gIHJldHVybiBzYW1wbGVzO1xufTtcblxuZXhwb3J0cy5pbnRlcnBvbGF0ZSA9IHZhbHVlO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZUFycmF5ID0gYXJyYXk7XG5leHBvcnRzLmludGVycG9sYXRlQmFzaXMgPSBiYXNpcyQxO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZUJhc2lzQ2xvc2VkID0gYmFzaXNDbG9zZWQ7XG5leHBvcnRzLmludGVycG9sYXRlRGF0ZSA9IGRhdGU7XG5leHBvcnRzLmludGVycG9sYXRlTnVtYmVyID0gbnVtYmVyO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZU9iamVjdCA9IG9iamVjdDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVSb3VuZCA9IHJvdW5kO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZVN0cmluZyA9IHN0cmluZztcbmV4cG9ydHMuaW50ZXJwb2xhdGVUcmFuc2Zvcm1Dc3MgPSBpbnRlcnBvbGF0ZVRyYW5zZm9ybUNzcztcbmV4cG9ydHMuaW50ZXJwb2xhdGVUcmFuc2Zvcm1TdmcgPSBpbnRlcnBvbGF0ZVRyYW5zZm9ybVN2ZztcbmV4cG9ydHMuaW50ZXJwb2xhdGVab29tID0gem9vbTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVSZ2IgPSByZ2IkMTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVSZ2JCYXNpcyA9IHJnYkJhc2lzO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZVJnYkJhc2lzQ2xvc2VkID0gcmdiQmFzaXNDbG9zZWQ7XG5leHBvcnRzLmludGVycG9sYXRlSHNsID0gaHNsJDI7XG5leHBvcnRzLmludGVycG9sYXRlSHNsTG9uZyA9IGhzbExvbmc7XG5leHBvcnRzLmludGVycG9sYXRlTGFiID0gbGFiJDE7XG5leHBvcnRzLmludGVycG9sYXRlSGNsID0gaGNsJDI7XG5leHBvcnRzLmludGVycG9sYXRlSGNsTG9uZyA9IGhjbExvbmc7XG5leHBvcnRzLmludGVycG9sYXRlQ3ViZWhlbGl4ID0gY3ViZWhlbGl4JDI7XG5leHBvcnRzLmludGVycG9sYXRlQ3ViZWhlbGl4TG9uZyA9IGN1YmVoZWxpeExvbmc7XG5leHBvcnRzLnF1YW50aXplID0gcXVhbnRpemU7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLXBhdGgvIFZlcnNpb24gMS4wLjUuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIHBpID0gTWF0aC5QSTtcbnZhciB0YXUgPSAyICogcGk7XG52YXIgZXBzaWxvbiA9IDFlLTY7XG52YXIgdGF1RXBzaWxvbiA9IHRhdSAtIGVwc2lsb247XG5cbmZ1bmN0aW9uIFBhdGgoKSB7XG4gIHRoaXMuX3gwID0gdGhpcy5feTAgPSAvLyBzdGFydCBvZiBjdXJyZW50IHN1YnBhdGhcbiAgdGhpcy5feDEgPSB0aGlzLl95MSA9IG51bGw7IC8vIGVuZCBvZiBjdXJyZW50IHN1YnBhdGhcbiAgdGhpcy5fID0gXCJcIjtcbn1cblxuZnVuY3Rpb24gcGF0aCgpIHtcbiAgcmV0dXJuIG5ldyBQYXRoO1xufVxuXG5QYXRoLnByb3RvdHlwZSA9IHBhdGgucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogUGF0aCxcbiAgbW92ZVRvOiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdGhpcy5fICs9IFwiTVwiICsgKHRoaXMuX3gwID0gdGhpcy5feDEgPSAreCkgKyBcIixcIiArICh0aGlzLl95MCA9IHRoaXMuX3kxID0gK3kpO1xuICB9LFxuICBjbG9zZVBhdGg6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl94MSAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5feDEgPSB0aGlzLl94MCwgdGhpcy5feTEgPSB0aGlzLl95MDtcbiAgICAgIHRoaXMuXyArPSBcIlpcIjtcbiAgICB9XG4gIH0sXG4gIGxpbmVUbzogZnVuY3Rpb24oeCwgeSkge1xuICAgIHRoaXMuXyArPSBcIkxcIiArICh0aGlzLl94MSA9ICt4KSArIFwiLFwiICsgKHRoaXMuX3kxID0gK3kpO1xuICB9LFxuICBxdWFkcmF0aWNDdXJ2ZVRvOiBmdW5jdGlvbih4MSwgeTEsIHgsIHkpIHtcbiAgICB0aGlzLl8gKz0gXCJRXCIgKyAoK3gxKSArIFwiLFwiICsgKCt5MSkgKyBcIixcIiArICh0aGlzLl94MSA9ICt4KSArIFwiLFwiICsgKHRoaXMuX3kxID0gK3kpO1xuICB9LFxuICBiZXppZXJDdXJ2ZVRvOiBmdW5jdGlvbih4MSwgeTEsIHgyLCB5MiwgeCwgeSkge1xuICAgIHRoaXMuXyArPSBcIkNcIiArICgreDEpICsgXCIsXCIgKyAoK3kxKSArIFwiLFwiICsgKCt4MikgKyBcIixcIiArICgreTIpICsgXCIsXCIgKyAodGhpcy5feDEgPSAreCkgKyBcIixcIiArICh0aGlzLl95MSA9ICt5KTtcbiAgfSxcbiAgYXJjVG86IGZ1bmN0aW9uKHgxLCB5MSwgeDIsIHkyLCByKSB7XG4gICAgeDEgPSAreDEsIHkxID0gK3kxLCB4MiA9ICt4MiwgeTIgPSAreTIsIHIgPSArcjtcbiAgICB2YXIgeDAgPSB0aGlzLl94MSxcbiAgICAgICAgeTAgPSB0aGlzLl95MSxcbiAgICAgICAgeDIxID0geDIgLSB4MSxcbiAgICAgICAgeTIxID0geTIgLSB5MSxcbiAgICAgICAgeDAxID0geDAgLSB4MSxcbiAgICAgICAgeTAxID0geTAgLSB5MSxcbiAgICAgICAgbDAxXzIgPSB4MDEgKiB4MDEgKyB5MDEgKiB5MDE7XG5cbiAgICAvLyBJcyB0aGUgcmFkaXVzIG5lZ2F0aXZlPyBFcnJvci5cbiAgICBpZiAociA8IDApIHRocm93IG5ldyBFcnJvcihcIm5lZ2F0aXZlIHJhZGl1czogXCIgKyByKTtcblxuICAgIC8vIElzIHRoaXMgcGF0aCBlbXB0eT8gTW92ZSB0byAoeDEseTEpLlxuICAgIGlmICh0aGlzLl94MSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5fICs9IFwiTVwiICsgKHRoaXMuX3gxID0geDEpICsgXCIsXCIgKyAodGhpcy5feTEgPSB5MSk7XG4gICAgfVxuXG4gICAgLy8gT3IsIGlzICh4MSx5MSkgY29pbmNpZGVudCB3aXRoICh4MCx5MCk/IERvIG5vdGhpbmcuXG4gICAgZWxzZSBpZiAoIShsMDFfMiA+IGVwc2lsb24pKSB7fVxuXG4gICAgLy8gT3IsIGFyZSAoeDAseTApLCAoeDEseTEpIGFuZCAoeDIseTIpIGNvbGxpbmVhcj9cbiAgICAvLyBFcXVpdmFsZW50bHksIGlzICh4MSx5MSkgY29pbmNpZGVudCB3aXRoICh4Mix5Mik/XG4gICAgLy8gT3IsIGlzIHRoZSByYWRpdXMgemVybz8gTGluZSB0byAoeDEseTEpLlxuICAgIGVsc2UgaWYgKCEoTWF0aC5hYnMoeTAxICogeDIxIC0geTIxICogeDAxKSA+IGVwc2lsb24pIHx8ICFyKSB7XG4gICAgICB0aGlzLl8gKz0gXCJMXCIgKyAodGhpcy5feDEgPSB4MSkgKyBcIixcIiArICh0aGlzLl95MSA9IHkxKTtcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UsIGRyYXcgYW4gYXJjIVxuICAgIGVsc2Uge1xuICAgICAgdmFyIHgyMCA9IHgyIC0geDAsXG4gICAgICAgICAgeTIwID0geTIgLSB5MCxcbiAgICAgICAgICBsMjFfMiA9IHgyMSAqIHgyMSArIHkyMSAqIHkyMSxcbiAgICAgICAgICBsMjBfMiA9IHgyMCAqIHgyMCArIHkyMCAqIHkyMCxcbiAgICAgICAgICBsMjEgPSBNYXRoLnNxcnQobDIxXzIpLFxuICAgICAgICAgIGwwMSA9IE1hdGguc3FydChsMDFfMiksXG4gICAgICAgICAgbCA9IHIgKiBNYXRoLnRhbigocGkgLSBNYXRoLmFjb3MoKGwyMV8yICsgbDAxXzIgLSBsMjBfMikgLyAoMiAqIGwyMSAqIGwwMSkpKSAvIDIpLFxuICAgICAgICAgIHQwMSA9IGwgLyBsMDEsXG4gICAgICAgICAgdDIxID0gbCAvIGwyMTtcblxuICAgICAgLy8gSWYgdGhlIHN0YXJ0IHRhbmdlbnQgaXMgbm90IGNvaW5jaWRlbnQgd2l0aCAoeDAseTApLCBsaW5lIHRvLlxuICAgICAgaWYgKE1hdGguYWJzKHQwMSAtIDEpID4gZXBzaWxvbikge1xuICAgICAgICB0aGlzLl8gKz0gXCJMXCIgKyAoeDEgKyB0MDEgKiB4MDEpICsgXCIsXCIgKyAoeTEgKyB0MDEgKiB5MDEpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl8gKz0gXCJBXCIgKyByICsgXCIsXCIgKyByICsgXCIsMCwwLFwiICsgKCsoeTAxICogeDIwID4geDAxICogeTIwKSkgKyBcIixcIiArICh0aGlzLl94MSA9IHgxICsgdDIxICogeDIxKSArIFwiLFwiICsgKHRoaXMuX3kxID0geTEgKyB0MjEgKiB5MjEpO1xuICAgIH1cbiAgfSxcbiAgYXJjOiBmdW5jdGlvbih4LCB5LCByLCBhMCwgYTEsIGNjdykge1xuICAgIHggPSAreCwgeSA9ICt5LCByID0gK3I7XG4gICAgdmFyIGR4ID0gciAqIE1hdGguY29zKGEwKSxcbiAgICAgICAgZHkgPSByICogTWF0aC5zaW4oYTApLFxuICAgICAgICB4MCA9IHggKyBkeCxcbiAgICAgICAgeTAgPSB5ICsgZHksXG4gICAgICAgIGN3ID0gMSBeIGNjdyxcbiAgICAgICAgZGEgPSBjY3cgPyBhMCAtIGExIDogYTEgLSBhMDtcblxuICAgIC8vIElzIHRoZSByYWRpdXMgbmVnYXRpdmU/IEVycm9yLlxuICAgIGlmIChyIDwgMCkgdGhyb3cgbmV3IEVycm9yKFwibmVnYXRpdmUgcmFkaXVzOiBcIiArIHIpO1xuXG4gICAgLy8gSXMgdGhpcyBwYXRoIGVtcHR5PyBNb3ZlIHRvICh4MCx5MCkuXG4gICAgaWYgKHRoaXMuX3gxID09PSBudWxsKSB7XG4gICAgICB0aGlzLl8gKz0gXCJNXCIgKyB4MCArIFwiLFwiICsgeTA7XG4gICAgfVxuXG4gICAgLy8gT3IsIGlzICh4MCx5MCkgbm90IGNvaW5jaWRlbnQgd2l0aCB0aGUgcHJldmlvdXMgcG9pbnQ/IExpbmUgdG8gKHgwLHkwKS5cbiAgICBlbHNlIGlmIChNYXRoLmFicyh0aGlzLl94MSAtIHgwKSA+IGVwc2lsb24gfHwgTWF0aC5hYnModGhpcy5feTEgLSB5MCkgPiBlcHNpbG9uKSB7XG4gICAgICB0aGlzLl8gKz0gXCJMXCIgKyB4MCArIFwiLFwiICsgeTA7XG4gICAgfVxuXG4gICAgLy8gSXMgdGhpcyBhcmMgZW1wdHk/IFdl4oCZcmUgZG9uZS5cbiAgICBpZiAoIXIpIHJldHVybjtcblxuICAgIC8vIERvZXMgdGhlIGFuZ2xlIGdvIHRoZSB3cm9uZyB3YXk/IEZsaXAgdGhlIGRpcmVjdGlvbi5cbiAgICBpZiAoZGEgPCAwKSBkYSA9IGRhICUgdGF1ICsgdGF1O1xuXG4gICAgLy8gSXMgdGhpcyBhIGNvbXBsZXRlIGNpcmNsZT8gRHJhdyB0d28gYXJjcyB0byBjb21wbGV0ZSB0aGUgY2lyY2xlLlxuICAgIGlmIChkYSA+IHRhdUVwc2lsb24pIHtcbiAgICAgIHRoaXMuXyArPSBcIkFcIiArIHIgKyBcIixcIiArIHIgKyBcIiwwLDEsXCIgKyBjdyArIFwiLFwiICsgKHggLSBkeCkgKyBcIixcIiArICh5IC0gZHkpICsgXCJBXCIgKyByICsgXCIsXCIgKyByICsgXCIsMCwxLFwiICsgY3cgKyBcIixcIiArICh0aGlzLl94MSA9IHgwKSArIFwiLFwiICsgKHRoaXMuX3kxID0geTApO1xuICAgIH1cblxuICAgIC8vIElzIHRoaXMgYXJjIG5vbi1lbXB0eT8gRHJhdyBhbiBhcmMhXG4gICAgZWxzZSBpZiAoZGEgPiBlcHNpbG9uKSB7XG4gICAgICB0aGlzLl8gKz0gXCJBXCIgKyByICsgXCIsXCIgKyByICsgXCIsMCxcIiArICgrKGRhID49IHBpKSkgKyBcIixcIiArIGN3ICsgXCIsXCIgKyAodGhpcy5feDEgPSB4ICsgciAqIE1hdGguY29zKGExKSkgKyBcIixcIiArICh0aGlzLl95MSA9IHkgKyByICogTWF0aC5zaW4oYTEpKTtcbiAgICB9XG4gIH0sXG4gIHJlY3Q6IGZ1bmN0aW9uKHgsIHksIHcsIGgpIHtcbiAgICB0aGlzLl8gKz0gXCJNXCIgKyAodGhpcy5feDAgPSB0aGlzLl94MSA9ICt4KSArIFwiLFwiICsgKHRoaXMuX3kwID0gdGhpcy5feTEgPSAreSkgKyBcImhcIiArICgrdykgKyBcInZcIiArICgraCkgKyBcImhcIiArICgtdykgKyBcIlpcIjtcbiAgfSxcbiAgdG9TdHJpbmc6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl87XG4gIH1cbn07XG5cbmV4cG9ydHMucGF0aCA9IHBhdGg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLXBvbHlnb24vIFZlcnNpb24gMS4wLjMuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGFyZWEgPSBmdW5jdGlvbihwb2x5Z29uKSB7XG4gIHZhciBpID0gLTEsXG4gICAgICBuID0gcG9seWdvbi5sZW5ndGgsXG4gICAgICBhLFxuICAgICAgYiA9IHBvbHlnb25bbiAtIDFdLFxuICAgICAgYXJlYSA9IDA7XG5cbiAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICBhID0gYjtcbiAgICBiID0gcG9seWdvbltpXTtcbiAgICBhcmVhICs9IGFbMV0gKiBiWzBdIC0gYVswXSAqIGJbMV07XG4gIH1cblxuICByZXR1cm4gYXJlYSAvIDI7XG59O1xuXG52YXIgY2VudHJvaWQgPSBmdW5jdGlvbihwb2x5Z29uKSB7XG4gIHZhciBpID0gLTEsXG4gICAgICBuID0gcG9seWdvbi5sZW5ndGgsXG4gICAgICB4ID0gMCxcbiAgICAgIHkgPSAwLFxuICAgICAgYSxcbiAgICAgIGIgPSBwb2x5Z29uW24gLSAxXSxcbiAgICAgIGMsXG4gICAgICBrID0gMDtcblxuICB3aGlsZSAoKytpIDwgbikge1xuICAgIGEgPSBiO1xuICAgIGIgPSBwb2x5Z29uW2ldO1xuICAgIGsgKz0gYyA9IGFbMF0gKiBiWzFdIC0gYlswXSAqIGFbMV07XG4gICAgeCArPSAoYVswXSArIGJbMF0pICogYztcbiAgICB5ICs9IChhWzFdICsgYlsxXSkgKiBjO1xuICB9XG5cbiAgcmV0dXJuIGsgKj0gMywgW3ggLyBrLCB5IC8ga107XG59O1xuXG4vLyBSZXR1cm5zIHRoZSAyRCBjcm9zcyBwcm9kdWN0IG9mIEFCIGFuZCBBQyB2ZWN0b3JzLCBpLmUuLCB0aGUgei1jb21wb25lbnQgb2Zcbi8vIHRoZSAzRCBjcm9zcyBwcm9kdWN0IGluIGEgcXVhZHJhbnQgSSBDYXJ0ZXNpYW4gY29vcmRpbmF0ZSBzeXN0ZW0gKCt4IGlzXG4vLyByaWdodCwgK3kgaXMgdXApLiBSZXR1cm5zIGEgcG9zaXRpdmUgdmFsdWUgaWYgQUJDIGlzIGNvdW50ZXItY2xvY2t3aXNlLFxuLy8gbmVnYXRpdmUgaWYgY2xvY2t3aXNlLCBhbmQgemVybyBpZiB0aGUgcG9pbnRzIGFyZSBjb2xsaW5lYXIuXG52YXIgY3Jvc3MgPSBmdW5jdGlvbihhLCBiLCBjKSB7XG4gIHJldHVybiAoYlswXSAtIGFbMF0pICogKGNbMV0gLSBhWzFdKSAtIChiWzFdIC0gYVsxXSkgKiAoY1swXSAtIGFbMF0pO1xufTtcblxuZnVuY3Rpb24gbGV4aWNvZ3JhcGhpY09yZGVyKGEsIGIpIHtcbiAgcmV0dXJuIGFbMF0gLSBiWzBdIHx8IGFbMV0gLSBiWzFdO1xufVxuXG4vLyBDb21wdXRlcyB0aGUgdXBwZXIgY29udmV4IGh1bGwgcGVyIHRoZSBtb25vdG9uZSBjaGFpbiBhbGdvcml0aG0uXG4vLyBBc3N1bWVzIHBvaW50cy5sZW5ndGggPj0gMywgaXMgc29ydGVkIGJ5IHgsIHVuaXF1ZSBpbiB5LlxuLy8gUmV0dXJucyBhbiBhcnJheSBvZiBpbmRpY2VzIGludG8gcG9pbnRzIGluIGxlZnQtdG8tcmlnaHQgb3JkZXIuXG5mdW5jdGlvbiBjb21wdXRlVXBwZXJIdWxsSW5kZXhlcyhwb2ludHMpIHtcbiAgdmFyIG4gPSBwb2ludHMubGVuZ3RoLFxuICAgICAgaW5kZXhlcyA9IFswLCAxXSxcbiAgICAgIHNpemUgPSAyO1xuXG4gIGZvciAodmFyIGkgPSAyOyBpIDwgbjsgKytpKSB7XG4gICAgd2hpbGUgKHNpemUgPiAxICYmIGNyb3NzKHBvaW50c1tpbmRleGVzW3NpemUgLSAyXV0sIHBvaW50c1tpbmRleGVzW3NpemUgLSAxXV0sIHBvaW50c1tpXSkgPD0gMCkgLS1zaXplO1xuICAgIGluZGV4ZXNbc2l6ZSsrXSA9IGk7XG4gIH1cblxuICByZXR1cm4gaW5kZXhlcy5zbGljZSgwLCBzaXplKTsgLy8gcmVtb3ZlIHBvcHBlZCBwb2ludHNcbn1cblxudmFyIGh1bGwgPSBmdW5jdGlvbihwb2ludHMpIHtcbiAgaWYgKChuID0gcG9pbnRzLmxlbmd0aCkgPCAzKSByZXR1cm4gbnVsbDtcblxuICB2YXIgaSxcbiAgICAgIG4sXG4gICAgICBzb3J0ZWRQb2ludHMgPSBuZXcgQXJyYXkobiksXG4gICAgICBmbGlwcGVkUG9pbnRzID0gbmV3IEFycmF5KG4pO1xuXG4gIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHNvcnRlZFBvaW50c1tpXSA9IFsrcG9pbnRzW2ldWzBdLCArcG9pbnRzW2ldWzFdLCBpXTtcbiAgc29ydGVkUG9pbnRzLnNvcnQobGV4aWNvZ3JhcGhpY09yZGVyKTtcbiAgZm9yIChpID0gMDsgaSA8IG47ICsraSkgZmxpcHBlZFBvaW50c1tpXSA9IFtzb3J0ZWRQb2ludHNbaV1bMF0sIC1zb3J0ZWRQb2ludHNbaV1bMV1dO1xuXG4gIHZhciB1cHBlckluZGV4ZXMgPSBjb21wdXRlVXBwZXJIdWxsSW5kZXhlcyhzb3J0ZWRQb2ludHMpLFxuICAgICAgbG93ZXJJbmRleGVzID0gY29tcHV0ZVVwcGVySHVsbEluZGV4ZXMoZmxpcHBlZFBvaW50cyk7XG5cbiAgLy8gQ29uc3RydWN0IHRoZSBodWxsIHBvbHlnb24sIHJlbW92aW5nIHBvc3NpYmxlIGR1cGxpY2F0ZSBlbmRwb2ludHMuXG4gIHZhciBza2lwTGVmdCA9IGxvd2VySW5kZXhlc1swXSA9PT0gdXBwZXJJbmRleGVzWzBdLFxuICAgICAgc2tpcFJpZ2h0ID0gbG93ZXJJbmRleGVzW2xvd2VySW5kZXhlcy5sZW5ndGggLSAxXSA9PT0gdXBwZXJJbmRleGVzW3VwcGVySW5kZXhlcy5sZW5ndGggLSAxXSxcbiAgICAgIGh1bGwgPSBbXTtcblxuICAvLyBBZGQgdXBwZXIgaHVsbCBpbiByaWdodC10by1sIG9yZGVyLlxuICAvLyBUaGVuIGFkZCBsb3dlciBodWxsIGluIGxlZnQtdG8tcmlnaHQgb3JkZXIuXG4gIGZvciAoaSA9IHVwcGVySW5kZXhlcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgaHVsbC5wdXNoKHBvaW50c1tzb3J0ZWRQb2ludHNbdXBwZXJJbmRleGVzW2ldXVsyXV0pO1xuICBmb3IgKGkgPSArc2tpcExlZnQ7IGkgPCBsb3dlckluZGV4ZXMubGVuZ3RoIC0gc2tpcFJpZ2h0OyArK2kpIGh1bGwucHVzaChwb2ludHNbc29ydGVkUG9pbnRzW2xvd2VySW5kZXhlc1tpXV1bMl1dKTtcblxuICByZXR1cm4gaHVsbDtcbn07XG5cbnZhciBjb250YWlucyA9IGZ1bmN0aW9uKHBvbHlnb24sIHBvaW50KSB7XG4gIHZhciBuID0gcG9seWdvbi5sZW5ndGgsXG4gICAgICBwID0gcG9seWdvbltuIC0gMV0sXG4gICAgICB4ID0gcG9pbnRbMF0sIHkgPSBwb2ludFsxXSxcbiAgICAgIHgwID0gcFswXSwgeTAgPSBwWzFdLFxuICAgICAgeDEsIHkxLFxuICAgICAgaW5zaWRlID0gZmFsc2U7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICBwID0gcG9seWdvbltpXSwgeDEgPSBwWzBdLCB5MSA9IHBbMV07XG4gICAgaWYgKCgoeTEgPiB5KSAhPT0gKHkwID4geSkpICYmICh4IDwgKHgwIC0geDEpICogKHkgLSB5MSkgLyAoeTAgLSB5MSkgKyB4MSkpIGluc2lkZSA9ICFpbnNpZGU7XG4gICAgeDAgPSB4MSwgeTAgPSB5MTtcbiAgfVxuXG4gIHJldHVybiBpbnNpZGU7XG59O1xuXG52YXIgbGVuZ3RoID0gZnVuY3Rpb24ocG9seWdvbikge1xuICB2YXIgaSA9IC0xLFxuICAgICAgbiA9IHBvbHlnb24ubGVuZ3RoLFxuICAgICAgYiA9IHBvbHlnb25bbiAtIDFdLFxuICAgICAgeGEsXG4gICAgICB5YSxcbiAgICAgIHhiID0gYlswXSxcbiAgICAgIHliID0gYlsxXSxcbiAgICAgIHBlcmltZXRlciA9IDA7XG5cbiAgd2hpbGUgKCsraSA8IG4pIHtcbiAgICB4YSA9IHhiO1xuICAgIHlhID0geWI7XG4gICAgYiA9IHBvbHlnb25baV07XG4gICAgeGIgPSBiWzBdO1xuICAgIHliID0gYlsxXTtcbiAgICB4YSAtPSB4YjtcbiAgICB5YSAtPSB5YjtcbiAgICBwZXJpbWV0ZXIgKz0gTWF0aC5zcXJ0KHhhICogeGEgKyB5YSAqIHlhKTtcbiAgfVxuXG4gIHJldHVybiBwZXJpbWV0ZXI7XG59O1xuXG5leHBvcnRzLnBvbHlnb25BcmVhID0gYXJlYTtcbmV4cG9ydHMucG9seWdvbkNlbnRyb2lkID0gY2VudHJvaWQ7XG5leHBvcnRzLnBvbHlnb25IdWxsID0gaHVsbDtcbmV4cG9ydHMucG9seWdvbkNvbnRhaW5zID0gY29udGFpbnM7XG5leHBvcnRzLnBvbHlnb25MZW5ndGggPSBsZW5ndGg7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLXF1YWR0cmVlLyBWZXJzaW9uIDEuMC4zLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciB0cmVlX2FkZCA9IGZ1bmN0aW9uKGQpIHtcbiAgdmFyIHggPSArdGhpcy5feC5jYWxsKG51bGwsIGQpLFxuICAgICAgeSA9ICt0aGlzLl95LmNhbGwobnVsbCwgZCk7XG4gIHJldHVybiBhZGQodGhpcy5jb3Zlcih4LCB5KSwgeCwgeSwgZCk7XG59O1xuXG5mdW5jdGlvbiBhZGQodHJlZSwgeCwgeSwgZCkge1xuICBpZiAoaXNOYU4oeCkgfHwgaXNOYU4oeSkpIHJldHVybiB0cmVlOyAvLyBpZ25vcmUgaW52YWxpZCBwb2ludHNcblxuICB2YXIgcGFyZW50LFxuICAgICAgbm9kZSA9IHRyZWUuX3Jvb3QsXG4gICAgICBsZWFmID0ge2RhdGE6IGR9LFxuICAgICAgeDAgPSB0cmVlLl94MCxcbiAgICAgIHkwID0gdHJlZS5feTAsXG4gICAgICB4MSA9IHRyZWUuX3gxLFxuICAgICAgeTEgPSB0cmVlLl95MSxcbiAgICAgIHhtLFxuICAgICAgeW0sXG4gICAgICB4cCxcbiAgICAgIHlwLFxuICAgICAgcmlnaHQsXG4gICAgICBib3R0b20sXG4gICAgICBpLFxuICAgICAgajtcblxuICAvLyBJZiB0aGUgdHJlZSBpcyBlbXB0eSwgaW5pdGlhbGl6ZSB0aGUgcm9vdCBhcyBhIGxlYWYuXG4gIGlmICghbm9kZSkgcmV0dXJuIHRyZWUuX3Jvb3QgPSBsZWFmLCB0cmVlO1xuXG4gIC8vIEZpbmQgdGhlIGV4aXN0aW5nIGxlYWYgZm9yIHRoZSBuZXcgcG9pbnQsIG9yIGFkZCBpdC5cbiAgd2hpbGUgKG5vZGUubGVuZ3RoKSB7XG4gICAgaWYgKHJpZ2h0ID0geCA+PSAoeG0gPSAoeDAgKyB4MSkgLyAyKSkgeDAgPSB4bTsgZWxzZSB4MSA9IHhtO1xuICAgIGlmIChib3R0b20gPSB5ID49ICh5bSA9ICh5MCArIHkxKSAvIDIpKSB5MCA9IHltOyBlbHNlIHkxID0geW07XG4gICAgaWYgKHBhcmVudCA9IG5vZGUsICEobm9kZSA9IG5vZGVbaSA9IGJvdHRvbSA8PCAxIHwgcmlnaHRdKSkgcmV0dXJuIHBhcmVudFtpXSA9IGxlYWYsIHRyZWU7XG4gIH1cblxuICAvLyBJcyB0aGUgbmV3IHBvaW50IGlzIGV4YWN0bHkgY29pbmNpZGVudCB3aXRoIHRoZSBleGlzdGluZyBwb2ludD9cbiAgeHAgPSArdHJlZS5feC5jYWxsKG51bGwsIG5vZGUuZGF0YSk7XG4gIHlwID0gK3RyZWUuX3kuY2FsbChudWxsLCBub2RlLmRhdGEpO1xuICBpZiAoeCA9PT0geHAgJiYgeSA9PT0geXApIHJldHVybiBsZWFmLm5leHQgPSBub2RlLCBwYXJlbnQgPyBwYXJlbnRbaV0gPSBsZWFmIDogdHJlZS5fcm9vdCA9IGxlYWYsIHRyZWU7XG5cbiAgLy8gT3RoZXJ3aXNlLCBzcGxpdCB0aGUgbGVhZiBub2RlIHVudGlsIHRoZSBvbGQgYW5kIG5ldyBwb2ludCBhcmUgc2VwYXJhdGVkLlxuICBkbyB7XG4gICAgcGFyZW50ID0gcGFyZW50ID8gcGFyZW50W2ldID0gbmV3IEFycmF5KDQpIDogdHJlZS5fcm9vdCA9IG5ldyBBcnJheSg0KTtcbiAgICBpZiAocmlnaHQgPSB4ID49ICh4bSA9ICh4MCArIHgxKSAvIDIpKSB4MCA9IHhtOyBlbHNlIHgxID0geG07XG4gICAgaWYgKGJvdHRvbSA9IHkgPj0gKHltID0gKHkwICsgeTEpIC8gMikpIHkwID0geW07IGVsc2UgeTEgPSB5bTtcbiAgfSB3aGlsZSAoKGkgPSBib3R0b20gPDwgMSB8IHJpZ2h0KSA9PT0gKGogPSAoeXAgPj0geW0pIDw8IDEgfCAoeHAgPj0geG0pKSk7XG4gIHJldHVybiBwYXJlbnRbal0gPSBub2RlLCBwYXJlbnRbaV0gPSBsZWFmLCB0cmVlO1xufVxuXG5mdW5jdGlvbiBhZGRBbGwoZGF0YSkge1xuICB2YXIgZCwgaSwgbiA9IGRhdGEubGVuZ3RoLFxuICAgICAgeCxcbiAgICAgIHksXG4gICAgICB4eiA9IG5ldyBBcnJheShuKSxcbiAgICAgIHl6ID0gbmV3IEFycmF5KG4pLFxuICAgICAgeDAgPSBJbmZpbml0eSxcbiAgICAgIHkwID0gSW5maW5pdHksXG4gICAgICB4MSA9IC1JbmZpbml0eSxcbiAgICAgIHkxID0gLUluZmluaXR5O1xuXG4gIC8vIENvbXB1dGUgdGhlIHBvaW50cyBhbmQgdGhlaXIgZXh0ZW50LlxuICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgaWYgKGlzTmFOKHggPSArdGhpcy5feC5jYWxsKG51bGwsIGQgPSBkYXRhW2ldKSkgfHwgaXNOYU4oeSA9ICt0aGlzLl95LmNhbGwobnVsbCwgZCkpKSBjb250aW51ZTtcbiAgICB4eltpXSA9IHg7XG4gICAgeXpbaV0gPSB5O1xuICAgIGlmICh4IDwgeDApIHgwID0geDtcbiAgICBpZiAoeCA+IHgxKSB4MSA9IHg7XG4gICAgaWYgKHkgPCB5MCkgeTAgPSB5O1xuICAgIGlmICh5ID4geTEpIHkxID0geTtcbiAgfVxuXG4gIC8vIElmIHRoZXJlIHdlcmUgbm8gKHZhbGlkKSBwb2ludHMsIGluaGVyaXQgdGhlIGV4aXN0aW5nIGV4dGVudC5cbiAgaWYgKHgxIDwgeDApIHgwID0gdGhpcy5feDAsIHgxID0gdGhpcy5feDE7XG4gIGlmICh5MSA8IHkwKSB5MCA9IHRoaXMuX3kwLCB5MSA9IHRoaXMuX3kxO1xuXG4gIC8vIEV4cGFuZCB0aGUgdHJlZSB0byBjb3ZlciB0aGUgbmV3IHBvaW50cy5cbiAgdGhpcy5jb3Zlcih4MCwgeTApLmNvdmVyKHgxLCB5MSk7XG5cbiAgLy8gQWRkIHRoZSBuZXcgcG9pbnRzLlxuICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgYWRkKHRoaXMsIHh6W2ldLCB5eltpXSwgZGF0YVtpXSk7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn1cblxudmFyIHRyZWVfY292ZXIgPSBmdW5jdGlvbih4LCB5KSB7XG4gIGlmIChpc05hTih4ID0gK3gpIHx8IGlzTmFOKHkgPSAreSkpIHJldHVybiB0aGlzOyAvLyBpZ25vcmUgaW52YWxpZCBwb2ludHNcblxuICB2YXIgeDAgPSB0aGlzLl94MCxcbiAgICAgIHkwID0gdGhpcy5feTAsXG4gICAgICB4MSA9IHRoaXMuX3gxLFxuICAgICAgeTEgPSB0aGlzLl95MTtcblxuICAvLyBJZiB0aGUgcXVhZHRyZWUgaGFzIG5vIGV4dGVudCwgaW5pdGlhbGl6ZSB0aGVtLlxuICAvLyBJbnRlZ2VyIGV4dGVudCBhcmUgbmVjZXNzYXJ5IHNvIHRoYXQgaWYgd2UgbGF0ZXIgZG91YmxlIHRoZSBleHRlbnQsXG4gIC8vIHRoZSBleGlzdGluZyBxdWFkcmFudCBib3VuZGFyaWVzIGRvbuKAmXQgY2hhbmdlIGR1ZSB0byBmbG9hdGluZyBwb2ludCBlcnJvciFcbiAgaWYgKGlzTmFOKHgwKSkge1xuICAgIHgxID0gKHgwID0gTWF0aC5mbG9vcih4KSkgKyAxO1xuICAgIHkxID0gKHkwID0gTWF0aC5mbG9vcih5KSkgKyAxO1xuICB9XG5cbiAgLy8gT3RoZXJ3aXNlLCBkb3VibGUgcmVwZWF0ZWRseSB0byBjb3Zlci5cbiAgZWxzZSBpZiAoeDAgPiB4IHx8IHggPiB4MSB8fCB5MCA+IHkgfHwgeSA+IHkxKSB7XG4gICAgdmFyIHogPSB4MSAtIHgwLFxuICAgICAgICBub2RlID0gdGhpcy5fcm9vdCxcbiAgICAgICAgcGFyZW50LFxuICAgICAgICBpO1xuXG4gICAgc3dpdGNoIChpID0gKHkgPCAoeTAgKyB5MSkgLyAyKSA8PCAxIHwgKHggPCAoeDAgKyB4MSkgLyAyKSkge1xuICAgICAgY2FzZSAwOiB7XG4gICAgICAgIGRvIHBhcmVudCA9IG5ldyBBcnJheSg0KSwgcGFyZW50W2ldID0gbm9kZSwgbm9kZSA9IHBhcmVudDtcbiAgICAgICAgd2hpbGUgKHogKj0gMiwgeDEgPSB4MCArIHosIHkxID0geTAgKyB6LCB4ID4geDEgfHwgeSA+IHkxKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDE6IHtcbiAgICAgICAgZG8gcGFyZW50ID0gbmV3IEFycmF5KDQpLCBwYXJlbnRbaV0gPSBub2RlLCBub2RlID0gcGFyZW50O1xuICAgICAgICB3aGlsZSAoeiAqPSAyLCB4MCA9IHgxIC0geiwgeTEgPSB5MCArIHosIHgwID4geCB8fCB5ID4geTEpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgMjoge1xuICAgICAgICBkbyBwYXJlbnQgPSBuZXcgQXJyYXkoNCksIHBhcmVudFtpXSA9IG5vZGUsIG5vZGUgPSBwYXJlbnQ7XG4gICAgICAgIHdoaWxlICh6ICo9IDIsIHgxID0geDAgKyB6LCB5MCA9IHkxIC0geiwgeCA+IHgxIHx8IHkwID4geSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAzOiB7XG4gICAgICAgIGRvIHBhcmVudCA9IG5ldyBBcnJheSg0KSwgcGFyZW50W2ldID0gbm9kZSwgbm9kZSA9IHBhcmVudDtcbiAgICAgICAgd2hpbGUgKHogKj0gMiwgeDAgPSB4MSAtIHosIHkwID0geTEgLSB6LCB4MCA+IHggfHwgeTAgPiB5KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX3Jvb3QgJiYgdGhpcy5fcm9vdC5sZW5ndGgpIHRoaXMuX3Jvb3QgPSBub2RlO1xuICB9XG5cbiAgLy8gSWYgdGhlIHF1YWR0cmVlIGNvdmVycyB0aGUgcG9pbnQgYWxyZWFkeSwganVzdCByZXR1cm4uXG4gIGVsc2UgcmV0dXJuIHRoaXM7XG5cbiAgdGhpcy5feDAgPSB4MDtcbiAgdGhpcy5feTAgPSB5MDtcbiAgdGhpcy5feDEgPSB4MTtcbiAgdGhpcy5feTEgPSB5MTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG52YXIgdHJlZV9kYXRhID0gZnVuY3Rpb24oKSB7XG4gIHZhciBkYXRhID0gW107XG4gIHRoaXMudmlzaXQoZnVuY3Rpb24obm9kZSkge1xuICAgIGlmICghbm9kZS5sZW5ndGgpIGRvIGRhdGEucHVzaChub2RlLmRhdGEpOyB3aGlsZSAobm9kZSA9IG5vZGUubmV4dClcbiAgfSk7XG4gIHJldHVybiBkYXRhO1xufTtcblxudmFyIHRyZWVfZXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aFxuICAgICAgPyB0aGlzLmNvdmVyKCtfWzBdWzBdLCArX1swXVsxXSkuY292ZXIoK19bMV1bMF0sICtfWzFdWzFdKVxuICAgICAgOiBpc05hTih0aGlzLl94MCkgPyB1bmRlZmluZWQgOiBbW3RoaXMuX3gwLCB0aGlzLl95MF0sIFt0aGlzLl94MSwgdGhpcy5feTFdXTtcbn07XG5cbnZhciBRdWFkID0gZnVuY3Rpb24obm9kZSwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgdGhpcy5ub2RlID0gbm9kZTtcbiAgdGhpcy54MCA9IHgwO1xuICB0aGlzLnkwID0geTA7XG4gIHRoaXMueDEgPSB4MTtcbiAgdGhpcy55MSA9IHkxO1xufTtcblxudmFyIHRyZWVfZmluZCA9IGZ1bmN0aW9uKHgsIHksIHJhZGl1cykge1xuICB2YXIgZGF0YSxcbiAgICAgIHgwID0gdGhpcy5feDAsXG4gICAgICB5MCA9IHRoaXMuX3kwLFxuICAgICAgeDEsXG4gICAgICB5MSxcbiAgICAgIHgyLFxuICAgICAgeTIsXG4gICAgICB4MyA9IHRoaXMuX3gxLFxuICAgICAgeTMgPSB0aGlzLl95MSxcbiAgICAgIHF1YWRzID0gW10sXG4gICAgICBub2RlID0gdGhpcy5fcm9vdCxcbiAgICAgIHEsXG4gICAgICBpO1xuXG4gIGlmIChub2RlKSBxdWFkcy5wdXNoKG5ldyBRdWFkKG5vZGUsIHgwLCB5MCwgeDMsIHkzKSk7XG4gIGlmIChyYWRpdXMgPT0gbnVsbCkgcmFkaXVzID0gSW5maW5pdHk7XG4gIGVsc2Uge1xuICAgIHgwID0geCAtIHJhZGl1cywgeTAgPSB5IC0gcmFkaXVzO1xuICAgIHgzID0geCArIHJhZGl1cywgeTMgPSB5ICsgcmFkaXVzO1xuICAgIHJhZGl1cyAqPSByYWRpdXM7XG4gIH1cblxuICB3aGlsZSAocSA9IHF1YWRzLnBvcCgpKSB7XG5cbiAgICAvLyBTdG9wIHNlYXJjaGluZyBpZiB0aGlzIHF1YWRyYW50IGNhbuKAmXQgY29udGFpbiBhIGNsb3NlciBub2RlLlxuICAgIGlmICghKG5vZGUgPSBxLm5vZGUpXG4gICAgICAgIHx8ICh4MSA9IHEueDApID4geDNcbiAgICAgICAgfHwgKHkxID0gcS55MCkgPiB5M1xuICAgICAgICB8fCAoeDIgPSBxLngxKSA8IHgwXG4gICAgICAgIHx8ICh5MiA9IHEueTEpIDwgeTApIGNvbnRpbnVlO1xuXG4gICAgLy8gQmlzZWN0IHRoZSBjdXJyZW50IHF1YWRyYW50LlxuICAgIGlmIChub2RlLmxlbmd0aCkge1xuICAgICAgdmFyIHhtID0gKHgxICsgeDIpIC8gMixcbiAgICAgICAgICB5bSA9ICh5MSArIHkyKSAvIDI7XG5cbiAgICAgIHF1YWRzLnB1c2goXG4gICAgICAgIG5ldyBRdWFkKG5vZGVbM10sIHhtLCB5bSwgeDIsIHkyKSxcbiAgICAgICAgbmV3IFF1YWQobm9kZVsyXSwgeDEsIHltLCB4bSwgeTIpLFxuICAgICAgICBuZXcgUXVhZChub2RlWzFdLCB4bSwgeTEsIHgyLCB5bSksXG4gICAgICAgIG5ldyBRdWFkKG5vZGVbMF0sIHgxLCB5MSwgeG0sIHltKVxuICAgICAgKTtcblxuICAgICAgLy8gVmlzaXQgdGhlIGNsb3Nlc3QgcXVhZHJhbnQgZmlyc3QuXG4gICAgICBpZiAoaSA9ICh5ID49IHltKSA8PCAxIHwgKHggPj0geG0pKSB7XG4gICAgICAgIHEgPSBxdWFkc1txdWFkcy5sZW5ndGggLSAxXTtcbiAgICAgICAgcXVhZHNbcXVhZHMubGVuZ3RoIC0gMV0gPSBxdWFkc1txdWFkcy5sZW5ndGggLSAxIC0gaV07XG4gICAgICAgIHF1YWRzW3F1YWRzLmxlbmd0aCAtIDEgLSBpXSA9IHE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmlzaXQgdGhpcyBwb2ludC4gKFZpc2l0aW5nIGNvaW5jaWRlbnQgcG9pbnRzIGlzbuKAmXQgbmVjZXNzYXJ5ISlcbiAgICBlbHNlIHtcbiAgICAgIHZhciBkeCA9IHggLSArdGhpcy5feC5jYWxsKG51bGwsIG5vZGUuZGF0YSksXG4gICAgICAgICAgZHkgPSB5IC0gK3RoaXMuX3kuY2FsbChudWxsLCBub2RlLmRhdGEpLFxuICAgICAgICAgIGQyID0gZHggKiBkeCArIGR5ICogZHk7XG4gICAgICBpZiAoZDIgPCByYWRpdXMpIHtcbiAgICAgICAgdmFyIGQgPSBNYXRoLnNxcnQocmFkaXVzID0gZDIpO1xuICAgICAgICB4MCA9IHggLSBkLCB5MCA9IHkgLSBkO1xuICAgICAgICB4MyA9IHggKyBkLCB5MyA9IHkgKyBkO1xuICAgICAgICBkYXRhID0gbm9kZS5kYXRhO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkYXRhO1xufTtcblxudmFyIHRyZWVfcmVtb3ZlID0gZnVuY3Rpb24oZCkge1xuICBpZiAoaXNOYU4oeCA9ICt0aGlzLl94LmNhbGwobnVsbCwgZCkpIHx8IGlzTmFOKHkgPSArdGhpcy5feS5jYWxsKG51bGwsIGQpKSkgcmV0dXJuIHRoaXM7IC8vIGlnbm9yZSBpbnZhbGlkIHBvaW50c1xuXG4gIHZhciBwYXJlbnQsXG4gICAgICBub2RlID0gdGhpcy5fcm9vdCxcbiAgICAgIHJldGFpbmVyLFxuICAgICAgcHJldmlvdXMsXG4gICAgICBuZXh0LFxuICAgICAgeDAgPSB0aGlzLl94MCxcbiAgICAgIHkwID0gdGhpcy5feTAsXG4gICAgICB4MSA9IHRoaXMuX3gxLFxuICAgICAgeTEgPSB0aGlzLl95MSxcbiAgICAgIHgsXG4gICAgICB5LFxuICAgICAgeG0sXG4gICAgICB5bSxcbiAgICAgIHJpZ2h0LFxuICAgICAgYm90dG9tLFxuICAgICAgaSxcbiAgICAgIGo7XG5cbiAgLy8gSWYgdGhlIHRyZWUgaXMgZW1wdHksIGluaXRpYWxpemUgdGhlIHJvb3QgYXMgYSBsZWFmLlxuICBpZiAoIW5vZGUpIHJldHVybiB0aGlzO1xuXG4gIC8vIEZpbmQgdGhlIGxlYWYgbm9kZSBmb3IgdGhlIHBvaW50LlxuICAvLyBXaGlsZSBkZXNjZW5kaW5nLCBhbHNvIHJldGFpbiB0aGUgZGVlcGVzdCBwYXJlbnQgd2l0aCBhIG5vbi1yZW1vdmVkIHNpYmxpbmcuXG4gIGlmIChub2RlLmxlbmd0aCkgd2hpbGUgKHRydWUpIHtcbiAgICBpZiAocmlnaHQgPSB4ID49ICh4bSA9ICh4MCArIHgxKSAvIDIpKSB4MCA9IHhtOyBlbHNlIHgxID0geG07XG4gICAgaWYgKGJvdHRvbSA9IHkgPj0gKHltID0gKHkwICsgeTEpIC8gMikpIHkwID0geW07IGVsc2UgeTEgPSB5bTtcbiAgICBpZiAoIShwYXJlbnQgPSBub2RlLCBub2RlID0gbm9kZVtpID0gYm90dG9tIDw8IDEgfCByaWdodF0pKSByZXR1cm4gdGhpcztcbiAgICBpZiAoIW5vZGUubGVuZ3RoKSBicmVhaztcbiAgICBpZiAocGFyZW50WyhpICsgMSkgJiAzXSB8fCBwYXJlbnRbKGkgKyAyKSAmIDNdIHx8IHBhcmVudFsoaSArIDMpICYgM10pIHJldGFpbmVyID0gcGFyZW50LCBqID0gaTtcbiAgfVxuXG4gIC8vIEZpbmQgdGhlIHBvaW50IHRvIHJlbW92ZS5cbiAgd2hpbGUgKG5vZGUuZGF0YSAhPT0gZCkgaWYgKCEocHJldmlvdXMgPSBub2RlLCBub2RlID0gbm9kZS5uZXh0KSkgcmV0dXJuIHRoaXM7XG4gIGlmIChuZXh0ID0gbm9kZS5uZXh0KSBkZWxldGUgbm9kZS5uZXh0O1xuXG4gIC8vIElmIHRoZXJlIGFyZSBtdWx0aXBsZSBjb2luY2lkZW50IHBvaW50cywgcmVtb3ZlIGp1c3QgdGhlIHBvaW50LlxuICBpZiAocHJldmlvdXMpIHJldHVybiAobmV4dCA/IHByZXZpb3VzLm5leHQgPSBuZXh0IDogZGVsZXRlIHByZXZpb3VzLm5leHQpLCB0aGlzO1xuXG4gIC8vIElmIHRoaXMgaXMgdGhlIHJvb3QgcG9pbnQsIHJlbW92ZSBpdC5cbiAgaWYgKCFwYXJlbnQpIHJldHVybiB0aGlzLl9yb290ID0gbmV4dCwgdGhpcztcblxuICAvLyBSZW1vdmUgdGhpcyBsZWFmLlxuICBuZXh0ID8gcGFyZW50W2ldID0gbmV4dCA6IGRlbGV0ZSBwYXJlbnRbaV07XG5cbiAgLy8gSWYgdGhlIHBhcmVudCBub3cgY29udGFpbnMgZXhhY3RseSBvbmUgbGVhZiwgY29sbGFwc2Ugc3VwZXJmbHVvdXMgcGFyZW50cy5cbiAgaWYgKChub2RlID0gcGFyZW50WzBdIHx8IHBhcmVudFsxXSB8fCBwYXJlbnRbMl0gfHwgcGFyZW50WzNdKVxuICAgICAgJiYgbm9kZSA9PT0gKHBhcmVudFszXSB8fCBwYXJlbnRbMl0gfHwgcGFyZW50WzFdIHx8IHBhcmVudFswXSlcbiAgICAgICYmICFub2RlLmxlbmd0aCkge1xuICAgIGlmIChyZXRhaW5lcikgcmV0YWluZXJbal0gPSBub2RlO1xuICAgIGVsc2UgdGhpcy5fcm9vdCA9IG5vZGU7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uIHJlbW92ZUFsbChkYXRhKSB7XG4gIGZvciAodmFyIGkgPSAwLCBuID0gZGF0YS5sZW5ndGg7IGkgPCBuOyArK2kpIHRoaXMucmVtb3ZlKGRhdGFbaV0pO1xuICByZXR1cm4gdGhpcztcbn1cblxudmFyIHRyZWVfcm9vdCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5fcm9vdDtcbn07XG5cbnZhciB0cmVlX3NpemUgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHNpemUgPSAwO1xuICB0aGlzLnZpc2l0KGZ1bmN0aW9uKG5vZGUpIHtcbiAgICBpZiAoIW5vZGUubGVuZ3RoKSBkbyArK3NpemU7IHdoaWxlIChub2RlID0gbm9kZS5uZXh0KVxuICB9KTtcbiAgcmV0dXJuIHNpemU7XG59O1xuXG52YXIgdHJlZV92aXNpdCA9IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gIHZhciBxdWFkcyA9IFtdLCBxLCBub2RlID0gdGhpcy5fcm9vdCwgY2hpbGQsIHgwLCB5MCwgeDEsIHkxO1xuICBpZiAobm9kZSkgcXVhZHMucHVzaChuZXcgUXVhZChub2RlLCB0aGlzLl94MCwgdGhpcy5feTAsIHRoaXMuX3gxLCB0aGlzLl95MSkpO1xuICB3aGlsZSAocSA9IHF1YWRzLnBvcCgpKSB7XG4gICAgaWYgKCFjYWxsYmFjayhub2RlID0gcS5ub2RlLCB4MCA9IHEueDAsIHkwID0gcS55MCwgeDEgPSBxLngxLCB5MSA9IHEueTEpICYmIG5vZGUubGVuZ3RoKSB7XG4gICAgICB2YXIgeG0gPSAoeDAgKyB4MSkgLyAyLCB5bSA9ICh5MCArIHkxKSAvIDI7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzNdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4bSwgeW0sIHgxLCB5MSkpO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVsyXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeDAsIHltLCB4bSwgeTEpKTtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbMV0pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHhtLCB5MCwgeDEsIHltKSk7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzBdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4MCwgeTAsIHhtLCB5bSkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbnZhciB0cmVlX3Zpc2l0QWZ0ZXIgPSBmdW5jdGlvbihjYWxsYmFjaykge1xuICB2YXIgcXVhZHMgPSBbXSwgbmV4dCA9IFtdLCBxO1xuICBpZiAodGhpcy5fcm9vdCkgcXVhZHMucHVzaChuZXcgUXVhZCh0aGlzLl9yb290LCB0aGlzLl94MCwgdGhpcy5feTAsIHRoaXMuX3gxLCB0aGlzLl95MSkpO1xuICB3aGlsZSAocSA9IHF1YWRzLnBvcCgpKSB7XG4gICAgdmFyIG5vZGUgPSBxLm5vZGU7XG4gICAgaWYgKG5vZGUubGVuZ3RoKSB7XG4gICAgICB2YXIgY2hpbGQsIHgwID0gcS54MCwgeTAgPSBxLnkwLCB4MSA9IHEueDEsIHkxID0gcS55MSwgeG0gPSAoeDAgKyB4MSkgLyAyLCB5bSA9ICh5MCArIHkxKSAvIDI7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzBdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4MCwgeTAsIHhtLCB5bSkpO1xuICAgICAgaWYgKGNoaWxkID0gbm9kZVsxXSkgcXVhZHMucHVzaChuZXcgUXVhZChjaGlsZCwgeG0sIHkwLCB4MSwgeW0pKTtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGVbMl0pIHF1YWRzLnB1c2gobmV3IFF1YWQoY2hpbGQsIHgwLCB5bSwgeG0sIHkxKSk7XG4gICAgICBpZiAoY2hpbGQgPSBub2RlWzNdKSBxdWFkcy5wdXNoKG5ldyBRdWFkKGNoaWxkLCB4bSwgeW0sIHgxLCB5MSkpO1xuICAgIH1cbiAgICBuZXh0LnB1c2gocSk7XG4gIH1cbiAgd2hpbGUgKHEgPSBuZXh0LnBvcCgpKSB7XG4gICAgY2FsbGJhY2socS5ub2RlLCBxLngwLCBxLnkwLCBxLngxLCBxLnkxKTtcbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uIGRlZmF1bHRYKGQpIHtcbiAgcmV0dXJuIGRbMF07XG59XG5cbnZhciB0cmVlX3ggPSBmdW5jdGlvbihfKSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRoaXMuX3ggPSBfLCB0aGlzKSA6IHRoaXMuX3g7XG59O1xuXG5mdW5jdGlvbiBkZWZhdWx0WShkKSB7XG4gIHJldHVybiBkWzFdO1xufVxuXG52YXIgdHJlZV95ID0gZnVuY3Rpb24oXykge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0aGlzLl95ID0gXywgdGhpcykgOiB0aGlzLl95O1xufTtcblxuZnVuY3Rpb24gcXVhZHRyZWUobm9kZXMsIHgsIHkpIHtcbiAgdmFyIHRyZWUgPSBuZXcgUXVhZHRyZWUoeCA9PSBudWxsID8gZGVmYXVsdFggOiB4LCB5ID09IG51bGwgPyBkZWZhdWx0WSA6IHksIE5hTiwgTmFOLCBOYU4sIE5hTik7XG4gIHJldHVybiBub2RlcyA9PSBudWxsID8gdHJlZSA6IHRyZWUuYWRkQWxsKG5vZGVzKTtcbn1cblxuZnVuY3Rpb24gUXVhZHRyZWUoeCwgeSwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgdGhpcy5feCA9IHg7XG4gIHRoaXMuX3kgPSB5O1xuICB0aGlzLl94MCA9IHgwO1xuICB0aGlzLl95MCA9IHkwO1xuICB0aGlzLl94MSA9IHgxO1xuICB0aGlzLl95MSA9IHkxO1xuICB0aGlzLl9yb290ID0gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBsZWFmX2NvcHkobGVhZikge1xuICB2YXIgY29weSA9IHtkYXRhOiBsZWFmLmRhdGF9LCBuZXh0ID0gY29weTtcbiAgd2hpbGUgKGxlYWYgPSBsZWFmLm5leHQpIG5leHQgPSBuZXh0Lm5leHQgPSB7ZGF0YTogbGVhZi5kYXRhfTtcbiAgcmV0dXJuIGNvcHk7XG59XG5cbnZhciB0cmVlUHJvdG8gPSBxdWFkdHJlZS5wcm90b3R5cGUgPSBRdWFkdHJlZS5wcm90b3R5cGU7XG5cbnRyZWVQcm90by5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBjb3B5ID0gbmV3IFF1YWR0cmVlKHRoaXMuX3gsIHRoaXMuX3ksIHRoaXMuX3gwLCB0aGlzLl95MCwgdGhpcy5feDEsIHRoaXMuX3kxKSxcbiAgICAgIG5vZGUgPSB0aGlzLl9yb290LFxuICAgICAgbm9kZXMsXG4gICAgICBjaGlsZDtcblxuICBpZiAoIW5vZGUpIHJldHVybiBjb3B5O1xuXG4gIGlmICghbm9kZS5sZW5ndGgpIHJldHVybiBjb3B5Ll9yb290ID0gbGVhZl9jb3B5KG5vZGUpLCBjb3B5O1xuXG4gIG5vZGVzID0gW3tzb3VyY2U6IG5vZGUsIHRhcmdldDogY29weS5fcm9vdCA9IG5ldyBBcnJheSg0KX1dO1xuICB3aGlsZSAobm9kZSA9IG5vZGVzLnBvcCgpKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyArK2kpIHtcbiAgICAgIGlmIChjaGlsZCA9IG5vZGUuc291cmNlW2ldKSB7XG4gICAgICAgIGlmIChjaGlsZC5sZW5ndGgpIG5vZGVzLnB1c2goe3NvdXJjZTogY2hpbGQsIHRhcmdldDogbm9kZS50YXJnZXRbaV0gPSBuZXcgQXJyYXkoNCl9KTtcbiAgICAgICAgZWxzZSBub2RlLnRhcmdldFtpXSA9IGxlYWZfY29weShjaGlsZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNvcHk7XG59O1xuXG50cmVlUHJvdG8uYWRkID0gdHJlZV9hZGQ7XG50cmVlUHJvdG8uYWRkQWxsID0gYWRkQWxsO1xudHJlZVByb3RvLmNvdmVyID0gdHJlZV9jb3ZlcjtcbnRyZWVQcm90by5kYXRhID0gdHJlZV9kYXRhO1xudHJlZVByb3RvLmV4dGVudCA9IHRyZWVfZXh0ZW50O1xudHJlZVByb3RvLmZpbmQgPSB0cmVlX2ZpbmQ7XG50cmVlUHJvdG8ucmVtb3ZlID0gdHJlZV9yZW1vdmU7XG50cmVlUHJvdG8ucmVtb3ZlQWxsID0gcmVtb3ZlQWxsO1xudHJlZVByb3RvLnJvb3QgPSB0cmVlX3Jvb3Q7XG50cmVlUHJvdG8uc2l6ZSA9IHRyZWVfc2l6ZTtcbnRyZWVQcm90by52aXNpdCA9IHRyZWVfdmlzaXQ7XG50cmVlUHJvdG8udmlzaXRBZnRlciA9IHRyZWVfdmlzaXRBZnRlcjtcbnRyZWVQcm90by54ID0gdHJlZV94O1xudHJlZVByb3RvLnkgPSB0cmVlX3k7XG5cbmV4cG9ydHMucXVhZHRyZWUgPSBxdWFkdHJlZTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtcXVldWUvIFZlcnNpb24gMy4wLjcuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIHNsaWNlID0gW10uc2xpY2U7XG5cbnZhciBub2Fib3J0ID0ge307XG5cbmZ1bmN0aW9uIFF1ZXVlKHNpemUpIHtcbiAgdGhpcy5fc2l6ZSA9IHNpemU7XG4gIHRoaXMuX2NhbGwgPVxuICB0aGlzLl9lcnJvciA9IG51bGw7XG4gIHRoaXMuX3Rhc2tzID0gW107XG4gIHRoaXMuX2RhdGEgPSBbXTtcbiAgdGhpcy5fd2FpdGluZyA9XG4gIHRoaXMuX2FjdGl2ZSA9XG4gIHRoaXMuX2VuZGVkID1cbiAgdGhpcy5fc3RhcnQgPSAwOyAvLyBpbnNpZGUgYSBzeW5jaHJvbm91cyB0YXNrIGNhbGxiYWNrP1xufVxuXG5RdWV1ZS5wcm90b3R5cGUgPSBxdWV1ZS5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBRdWV1ZSxcbiAgZGVmZXI6IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIGNhbGxiYWNrXCIpO1xuICAgIGlmICh0aGlzLl9jYWxsKSB0aHJvdyBuZXcgRXJyb3IoXCJkZWZlciBhZnRlciBhd2FpdFwiKTtcbiAgICBpZiAodGhpcy5fZXJyb3IgIT0gbnVsbCkgcmV0dXJuIHRoaXM7XG4gICAgdmFyIHQgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgdC5wdXNoKGNhbGxiYWNrKTtcbiAgICArK3RoaXMuX3dhaXRpbmcsIHRoaXMuX3Rhc2tzLnB1c2godCk7XG4gICAgcG9rZSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgYWJvcnQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl9lcnJvciA9PSBudWxsKSBhYm9ydCh0aGlzLCBuZXcgRXJyb3IoXCJhYm9ydFwiKSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG4gIGF3YWl0OiBmdW5jdGlvbihjYWxsYmFjaykge1xuICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBjYWxsYmFja1wiKTtcbiAgICBpZiAodGhpcy5fY2FsbCkgdGhyb3cgbmV3IEVycm9yKFwibXVsdGlwbGUgYXdhaXRcIik7XG4gICAgdGhpcy5fY2FsbCA9IGZ1bmN0aW9uKGVycm9yLCByZXN1bHRzKSB7IGNhbGxiYWNrLmFwcGx5KG51bGwsIFtlcnJvcl0uY29uY2F0KHJlc3VsdHMpKTsgfTtcbiAgICBtYXliZU5vdGlmeSh0aGlzKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfSxcbiAgYXdhaXRBbGw6IGZ1bmN0aW9uKGNhbGxiYWNrKSB7XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIGNhbGxiYWNrXCIpO1xuICAgIGlmICh0aGlzLl9jYWxsKSB0aHJvdyBuZXcgRXJyb3IoXCJtdWx0aXBsZSBhd2FpdFwiKTtcbiAgICB0aGlzLl9jYWxsID0gY2FsbGJhY2s7XG4gICAgbWF5YmVOb3RpZnkodGhpcyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHBva2UocSkge1xuICBpZiAoIXEuX3N0YXJ0KSB7XG4gICAgdHJ5IHsgc3RhcnQocSk7IH0gLy8gbGV0IHRoZSBjdXJyZW50IHRhc2sgY29tcGxldGVcbiAgICBjYXRjaCAoZSkge1xuICAgICAgaWYgKHEuX3Rhc2tzW3EuX2VuZGVkICsgcS5fYWN0aXZlIC0gMV0pIGFib3J0KHEsIGUpOyAvLyB0YXNrIGVycm9yZWQgc3luY2hyb25vdXNseVxuICAgICAgZWxzZSBpZiAoIXEuX2RhdGEpIHRocm93IGU7IC8vIGF3YWl0IGNhbGxiYWNrIGVycm9yZWQgc3luY2hyb25vdXNseVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzdGFydChxKSB7XG4gIHdoaWxlIChxLl9zdGFydCA9IHEuX3dhaXRpbmcgJiYgcS5fYWN0aXZlIDwgcS5fc2l6ZSkge1xuICAgIHZhciBpID0gcS5fZW5kZWQgKyBxLl9hY3RpdmUsXG4gICAgICAgIHQgPSBxLl90YXNrc1tpXSxcbiAgICAgICAgaiA9IHQubGVuZ3RoIC0gMSxcbiAgICAgICAgYyA9IHRbal07XG4gICAgdFtqXSA9IGVuZChxLCBpKTtcbiAgICAtLXEuX3dhaXRpbmcsICsrcS5fYWN0aXZlO1xuICAgIHQgPSBjLmFwcGx5KG51bGwsIHQpO1xuICAgIGlmICghcS5fdGFza3NbaV0pIGNvbnRpbnVlOyAvLyB0YXNrIGZpbmlzaGVkIHN5bmNocm9ub3VzbHlcbiAgICBxLl90YXNrc1tpXSA9IHQgfHwgbm9hYm9ydDtcbiAgfVxufVxuXG5mdW5jdGlvbiBlbmQocSwgaSkge1xuICByZXR1cm4gZnVuY3Rpb24oZSwgcikge1xuICAgIGlmICghcS5fdGFza3NbaV0pIHJldHVybjsgLy8gaWdub3JlIG11bHRpcGxlIGNhbGxiYWNrc1xuICAgIC0tcS5fYWN0aXZlLCArK3EuX2VuZGVkO1xuICAgIHEuX3Rhc2tzW2ldID0gbnVsbDtcbiAgICBpZiAocS5fZXJyb3IgIT0gbnVsbCkgcmV0dXJuOyAvLyBpZ25vcmUgc2Vjb25kYXJ5IGVycm9yc1xuICAgIGlmIChlICE9IG51bGwpIHtcbiAgICAgIGFib3J0KHEsIGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBxLl9kYXRhW2ldID0gcjtcbiAgICAgIGlmIChxLl93YWl0aW5nKSBwb2tlKHEpO1xuICAgICAgZWxzZSBtYXliZU5vdGlmeShxKTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGFib3J0KHEsIGUpIHtcbiAgdmFyIGkgPSBxLl90YXNrcy5sZW5ndGgsIHQ7XG4gIHEuX2Vycm9yID0gZTsgLy8gaWdub3JlIGFjdGl2ZSBjYWxsYmFja3NcbiAgcS5fZGF0YSA9IHVuZGVmaW5lZDsgLy8gYWxsb3cgZ2NcbiAgcS5fd2FpdGluZyA9IE5hTjsgLy8gcHJldmVudCBzdGFydGluZ1xuXG4gIHdoaWxlICgtLWkgPj0gMCkge1xuICAgIGlmICh0ID0gcS5fdGFza3NbaV0pIHtcbiAgICAgIHEuX3Rhc2tzW2ldID0gbnVsbDtcbiAgICAgIGlmICh0LmFib3J0KSB7XG4gICAgICAgIHRyeSB7IHQuYWJvcnQoKTsgfVxuICAgICAgICBjYXRjaCAoZSkgeyAvKiBpZ25vcmUgKi8gfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHEuX2FjdGl2ZSA9IE5hTjsgLy8gYWxsb3cgbm90aWZpY2F0aW9uXG4gIG1heWJlTm90aWZ5KHEpO1xufVxuXG5mdW5jdGlvbiBtYXliZU5vdGlmeShxKSB7XG4gIGlmICghcS5fYWN0aXZlICYmIHEuX2NhbGwpIHtcbiAgICB2YXIgZCA9IHEuX2RhdGE7XG4gICAgcS5fZGF0YSA9IHVuZGVmaW5lZDsgLy8gYWxsb3cgZ2NcbiAgICBxLl9jYWxsKHEuX2Vycm9yLCBkKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBxdWV1ZShjb25jdXJyZW5jeSkge1xuICBpZiAoY29uY3VycmVuY3kgPT0gbnVsbCkgY29uY3VycmVuY3kgPSBJbmZpbml0eTtcbiAgZWxzZSBpZiAoISgoY29uY3VycmVuY3kgPSArY29uY3VycmVuY3kpID49IDEpKSB0aHJvdyBuZXcgRXJyb3IoXCJpbnZhbGlkIGNvbmN1cnJlbmN5XCIpO1xuICByZXR1cm4gbmV3IFF1ZXVlKGNvbmN1cnJlbmN5KTtcbn1cblxuZXhwb3J0cy5xdWV1ZSA9IHF1ZXVlO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy1yYW5kb20vIFZlcnNpb24gMS4xLjAuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGRlZmF1bHRTb3VyY2UgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIE1hdGgucmFuZG9tKCk7XG59O1xuXG52YXIgdW5pZm9ybSA9ICgoZnVuY3Rpb24gc291cmNlUmFuZG9tVW5pZm9ybShzb3VyY2UpIHtcbiAgZnVuY3Rpb24gcmFuZG9tVW5pZm9ybShtaW4sIG1heCkge1xuICAgIG1pbiA9IG1pbiA9PSBudWxsID8gMCA6ICttaW47XG4gICAgbWF4ID0gbWF4ID09IG51bGwgPyAxIDogK21heDtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgbWF4ID0gbWluLCBtaW4gPSAwO1xuICAgIGVsc2UgbWF4IC09IG1pbjtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gc291cmNlKCkgKiBtYXggKyBtaW47XG4gICAgfTtcbiAgfVxuXG4gIHJhbmRvbVVuaWZvcm0uc291cmNlID0gc291cmNlUmFuZG9tVW5pZm9ybTtcblxuICByZXR1cm4gcmFuZG9tVW5pZm9ybTtcbn0pKShkZWZhdWx0U291cmNlKTtcblxudmFyIG5vcm1hbCA9ICgoZnVuY3Rpb24gc291cmNlUmFuZG9tTm9ybWFsKHNvdXJjZSkge1xuICBmdW5jdGlvbiByYW5kb21Ob3JtYWwobXUsIHNpZ21hKSB7XG4gICAgdmFyIHgsIHI7XG4gICAgbXUgPSBtdSA9PSBudWxsID8gMCA6ICttdTtcbiAgICBzaWdtYSA9IHNpZ21hID09IG51bGwgPyAxIDogK3NpZ21hO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciB5O1xuXG4gICAgICAvLyBJZiBhdmFpbGFibGUsIHVzZSB0aGUgc2Vjb25kIHByZXZpb3VzbHktZ2VuZXJhdGVkIHVuaWZvcm0gcmFuZG9tLlxuICAgICAgaWYgKHggIT0gbnVsbCkgeSA9IHgsIHggPSBudWxsO1xuXG4gICAgICAvLyBPdGhlcndpc2UsIGdlbmVyYXRlIGEgbmV3IHggYW5kIHkuXG4gICAgICBlbHNlIGRvIHtcbiAgICAgICAgeCA9IHNvdXJjZSgpICogMiAtIDE7XG4gICAgICAgIHkgPSBzb3VyY2UoKSAqIDIgLSAxO1xuICAgICAgICByID0geCAqIHggKyB5ICogeTtcbiAgICAgIH0gd2hpbGUgKCFyIHx8IHIgPiAxKTtcblxuICAgICAgcmV0dXJuIG11ICsgc2lnbWEgKiB5ICogTWF0aC5zcXJ0KC0yICogTWF0aC5sb2cocikgLyByKTtcbiAgICB9O1xuICB9XG5cbiAgcmFuZG9tTm9ybWFsLnNvdXJjZSA9IHNvdXJjZVJhbmRvbU5vcm1hbDtcblxuICByZXR1cm4gcmFuZG9tTm9ybWFsO1xufSkpKGRlZmF1bHRTb3VyY2UpO1xuXG52YXIgbG9nTm9ybWFsID0gKChmdW5jdGlvbiBzb3VyY2VSYW5kb21Mb2dOb3JtYWwoc291cmNlKSB7XG4gIGZ1bmN0aW9uIHJhbmRvbUxvZ05vcm1hbCgpIHtcbiAgICB2YXIgcmFuZG9tTm9ybWFsID0gbm9ybWFsLnNvdXJjZShzb3VyY2UpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIE1hdGguZXhwKHJhbmRvbU5vcm1hbCgpKTtcbiAgICB9O1xuICB9XG5cbiAgcmFuZG9tTG9nTm9ybWFsLnNvdXJjZSA9IHNvdXJjZVJhbmRvbUxvZ05vcm1hbDtcblxuICByZXR1cm4gcmFuZG9tTG9nTm9ybWFsO1xufSkpKGRlZmF1bHRTb3VyY2UpO1xuXG52YXIgaXJ3aW5IYWxsID0gKChmdW5jdGlvbiBzb3VyY2VSYW5kb21JcndpbkhhbGwoc291cmNlKSB7XG4gIGZ1bmN0aW9uIHJhbmRvbUlyd2luSGFsbChuKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgZm9yICh2YXIgc3VtID0gMCwgaSA9IDA7IGkgPCBuOyArK2kpIHN1bSArPSBzb3VyY2UoKTtcbiAgICAgIHJldHVybiBzdW07XG4gICAgfTtcbiAgfVxuXG4gIHJhbmRvbUlyd2luSGFsbC5zb3VyY2UgPSBzb3VyY2VSYW5kb21JcndpbkhhbGw7XG5cbiAgcmV0dXJuIHJhbmRvbUlyd2luSGFsbDtcbn0pKShkZWZhdWx0U291cmNlKTtcblxudmFyIGJhdGVzID0gKChmdW5jdGlvbiBzb3VyY2VSYW5kb21CYXRlcyhzb3VyY2UpIHtcbiAgZnVuY3Rpb24gcmFuZG9tQmF0ZXMobikge1xuICAgIHZhciByYW5kb21JcndpbkhhbGwgPSBpcndpbkhhbGwuc291cmNlKHNvdXJjZSkobik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHJhbmRvbUlyd2luSGFsbCgpIC8gbjtcbiAgICB9O1xuICB9XG5cbiAgcmFuZG9tQmF0ZXMuc291cmNlID0gc291cmNlUmFuZG9tQmF0ZXM7XG5cbiAgcmV0dXJuIHJhbmRvbUJhdGVzO1xufSkpKGRlZmF1bHRTb3VyY2UpO1xuXG52YXIgZXhwb25lbnRpYWwgPSAoKGZ1bmN0aW9uIHNvdXJjZVJhbmRvbUV4cG9uZW50aWFsKHNvdXJjZSkge1xuICBmdW5jdGlvbiByYW5kb21FeHBvbmVudGlhbChsYW1iZGEpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gLU1hdGgubG9nKDEgLSBzb3VyY2UoKSkgLyBsYW1iZGE7XG4gICAgfTtcbiAgfVxuXG4gIHJhbmRvbUV4cG9uZW50aWFsLnNvdXJjZSA9IHNvdXJjZVJhbmRvbUV4cG9uZW50aWFsO1xuXG4gIHJldHVybiByYW5kb21FeHBvbmVudGlhbDtcbn0pKShkZWZhdWx0U291cmNlKTtcblxuZXhwb3J0cy5yYW5kb21Vbmlmb3JtID0gdW5pZm9ybTtcbmV4cG9ydHMucmFuZG9tTm9ybWFsID0gbm9ybWFsO1xuZXhwb3J0cy5yYW5kb21Mb2dOb3JtYWwgPSBsb2dOb3JtYWw7XG5leHBvcnRzLnJhbmRvbUJhdGVzID0gYmF0ZXM7XG5leHBvcnRzLnJhbmRvbUlyd2luSGFsbCA9IGlyd2luSGFsbDtcbmV4cG9ydHMucmFuZG9tRXhwb25lbnRpYWwgPSBleHBvbmVudGlhbDtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFhNTEh0dHBSZXF1ZXN0ID0gcmVxdWlyZSgneG1saHR0cHJlcXVlc3QnKS5YTUxIdHRwUmVxdWVzdDtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxudmFyIGQzQ29sbGVjdGlvbiA9IHJlcXVpcmUoJ2QzLWNvbGxlY3Rpb24nKTtcbnZhciBkM0Rpc3BhdGNoID0gcmVxdWlyZSgnZDMtZGlzcGF0Y2gnKTtcbnZhciBkM0RzdiA9IHJlcXVpcmUoJ2QzLWRzdicpO1xuXG52YXIgcmVxdWVzdCA9IGZ1bmN0aW9uKHVybCwgY2FsbGJhY2spIHtcbiAgdmFyIHJlcXVlc3QsXG4gICAgICBldmVudCA9IGQzRGlzcGF0Y2guZGlzcGF0Y2goXCJiZWZvcmVzZW5kXCIsIFwicHJvZ3Jlc3NcIiwgXCJsb2FkXCIsIFwiZXJyb3JcIiksXG4gICAgICBtaW1lVHlwZSxcbiAgICAgIGhlYWRlcnMgPSBkM0NvbGxlY3Rpb24ubWFwKCksXG4gICAgICB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QsXG4gICAgICB1c2VyID0gbnVsbCxcbiAgICAgIHBhc3N3b3JkID0gbnVsbCxcbiAgICAgIHJlc3BvbnNlLFxuICAgICAgcmVzcG9uc2VUeXBlLFxuICAgICAgdGltZW91dCA9IDA7XG5cbiAgLy8gSWYgSUUgZG9lcyBub3Qgc3VwcG9ydCBDT1JTLCB1c2UgWERvbWFpblJlcXVlc3QuXG4gIGlmICh0eXBlb2YgWERvbWFpblJlcXVlc3QgIT09IFwidW5kZWZpbmVkXCJcbiAgICAgICYmICEoXCJ3aXRoQ3JlZGVudGlhbHNcIiBpbiB4aHIpXG4gICAgICAmJiAvXihodHRwKHMpPzopP1xcL1xcLy8udGVzdCh1cmwpKSB4aHIgPSBuZXcgWERvbWFpblJlcXVlc3Q7XG5cbiAgXCJvbmxvYWRcIiBpbiB4aHJcbiAgICAgID8geGhyLm9ubG9hZCA9IHhoci5vbmVycm9yID0geGhyLm9udGltZW91dCA9IHJlc3BvbmRcbiAgICAgIDogeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKG8pIHsgeGhyLnJlYWR5U3RhdGUgPiAzICYmIHJlc3BvbmQobyk7IH07XG5cbiAgZnVuY3Rpb24gcmVzcG9uZChvKSB7XG4gICAgdmFyIHN0YXR1cyA9IHhoci5zdGF0dXMsIHJlc3VsdDtcbiAgICBpZiAoIXN0YXR1cyAmJiBoYXNSZXNwb25zZSh4aHIpXG4gICAgICAgIHx8IHN0YXR1cyA+PSAyMDAgJiYgc3RhdHVzIDwgMzAwXG4gICAgICAgIHx8IHN0YXR1cyA9PT0gMzA0KSB7XG4gICAgICBpZiAocmVzcG9uc2UpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXN1bHQgPSByZXNwb25zZS5jYWxsKHJlcXVlc3QsIHhocik7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBldmVudC5jYWxsKFwiZXJyb3JcIiwgcmVxdWVzdCwgZSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQgPSB4aHI7XG4gICAgICB9XG4gICAgICBldmVudC5jYWxsKFwibG9hZFwiLCByZXF1ZXN0LCByZXN1bHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBldmVudC5jYWxsKFwiZXJyb3JcIiwgcmVxdWVzdCwgbyk7XG4gICAgfVxuICB9XG5cbiAgeGhyLm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbihlKSB7XG4gICAgZXZlbnQuY2FsbChcInByb2dyZXNzXCIsIHJlcXVlc3QsIGUpO1xuICB9O1xuXG4gIHJlcXVlc3QgPSB7XG4gICAgaGVhZGVyOiBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICAgICAgbmFtZSA9IChuYW1lICsgXCJcIikudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcmV0dXJuIGhlYWRlcnMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKHZhbHVlID09IG51bGwpIGhlYWRlcnMucmVtb3ZlKG5hbWUpO1xuICAgICAgZWxzZSBoZWFkZXJzLnNldChuYW1lLCB2YWx1ZSArIFwiXCIpO1xuICAgICAgcmV0dXJuIHJlcXVlc3Q7XG4gICAgfSxcblxuICAgIC8vIElmIG1pbWVUeXBlIGlzIG5vbi1udWxsIGFuZCBubyBBY2NlcHQgaGVhZGVyIGlzIHNldCwgYSBkZWZhdWx0IGlzIHVzZWQuXG4gICAgbWltZVR5cGU6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBtaW1lVHlwZTtcbiAgICAgIG1pbWVUeXBlID0gdmFsdWUgPT0gbnVsbCA/IG51bGwgOiB2YWx1ZSArIFwiXCI7XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9LFxuXG4gICAgLy8gU3BlY2lmaWVzIHdoYXQgdHlwZSB0aGUgcmVzcG9uc2UgdmFsdWUgc2hvdWxkIHRha2U7XG4gICAgLy8gZm9yIGluc3RhbmNlLCBhcnJheWJ1ZmZlciwgYmxvYiwgZG9jdW1lbnQsIG9yIHRleHQuXG4gICAgcmVzcG9uc2VUeXBlOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gcmVzcG9uc2VUeXBlO1xuICAgICAgcmVzcG9uc2VUeXBlID0gdmFsdWU7XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9LFxuXG4gICAgdGltZW91dDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIHRpbWVvdXQ7XG4gICAgICB0aW1lb3V0ID0gK3ZhbHVlO1xuICAgICAgcmV0dXJuIHJlcXVlc3Q7XG4gICAgfSxcblxuICAgIHVzZXI6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA8IDEgPyB1c2VyIDogKHVzZXIgPSB2YWx1ZSA9PSBudWxsID8gbnVsbCA6IHZhbHVlICsgXCJcIiwgcmVxdWVzdCk7XG4gICAgfSxcblxuICAgIHBhc3N3b3JkOiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPCAxID8gcGFzc3dvcmQgOiAocGFzc3dvcmQgPSB2YWx1ZSA9PSBudWxsID8gbnVsbCA6IHZhbHVlICsgXCJcIiwgcmVxdWVzdCk7XG4gICAgfSxcblxuICAgIC8vIFNwZWNpZnkgaG93IHRvIGNvbnZlcnQgdGhlIHJlc3BvbnNlIGNvbnRlbnQgdG8gYSBzcGVjaWZpYyB0eXBlO1xuICAgIC8vIGNoYW5nZXMgdGhlIGNhbGxiYWNrIHZhbHVlIG9uIFwibG9hZFwiIGV2ZW50cy5cbiAgICByZXNwb25zZTogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJlc3BvbnNlID0gdmFsdWU7XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9LFxuXG4gICAgLy8gQWxpYXMgZm9yIHNlbmQoXCJHRVRcIiwg4oCmKS5cbiAgICBnZXQ6IGZ1bmN0aW9uKGRhdGEsIGNhbGxiYWNrKSB7XG4gICAgICByZXR1cm4gcmVxdWVzdC5zZW5kKFwiR0VUXCIsIGRhdGEsIGNhbGxiYWNrKTtcbiAgICB9LFxuXG4gICAgLy8gQWxpYXMgZm9yIHNlbmQoXCJQT1NUXCIsIOKApikuXG4gICAgcG9zdDogZnVuY3Rpb24oZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgIHJldHVybiByZXF1ZXN0LnNlbmQoXCJQT1NUXCIsIGRhdGEsIGNhbGxiYWNrKTtcbiAgICB9LFxuXG4gICAgLy8gSWYgY2FsbGJhY2sgaXMgbm9uLW51bGwsIGl0IHdpbGwgYmUgdXNlZCBmb3IgZXJyb3IgYW5kIGxvYWQgZXZlbnRzLlxuICAgIHNlbmQ6IGZ1bmN0aW9uKG1ldGhvZCwgZGF0YSwgY2FsbGJhY2spIHtcbiAgICAgIHhoci5vcGVuKG1ldGhvZCwgdXJsLCB0cnVlLCB1c2VyLCBwYXNzd29yZCk7XG4gICAgICBpZiAobWltZVR5cGUgIT0gbnVsbCAmJiAhaGVhZGVycy5oYXMoXCJhY2NlcHRcIikpIGhlYWRlcnMuc2V0KFwiYWNjZXB0XCIsIG1pbWVUeXBlICsgXCIsKi8qXCIpO1xuICAgICAgaWYgKHhoci5zZXRSZXF1ZXN0SGVhZGVyKSBoZWFkZXJzLmVhY2goZnVuY3Rpb24odmFsdWUsIG5hbWUpIHsgeGhyLnNldFJlcXVlc3RIZWFkZXIobmFtZSwgdmFsdWUpOyB9KTtcbiAgICAgIGlmIChtaW1lVHlwZSAhPSBudWxsICYmIHhoci5vdmVycmlkZU1pbWVUeXBlKSB4aHIub3ZlcnJpZGVNaW1lVHlwZShtaW1lVHlwZSk7XG4gICAgICBpZiAocmVzcG9uc2VUeXBlICE9IG51bGwpIHhoci5yZXNwb25zZVR5cGUgPSByZXNwb25zZVR5cGU7XG4gICAgICBpZiAodGltZW91dCA+IDApIHhoci50aW1lb3V0ID0gdGltZW91dDtcbiAgICAgIGlmIChjYWxsYmFjayA9PSBudWxsICYmIHR5cGVvZiBkYXRhID09PSBcImZ1bmN0aW9uXCIpIGNhbGxiYWNrID0gZGF0YSwgZGF0YSA9IG51bGw7XG4gICAgICBpZiAoY2FsbGJhY2sgIT0gbnVsbCAmJiBjYWxsYmFjay5sZW5ndGggPT09IDEpIGNhbGxiYWNrID0gZml4Q2FsbGJhY2soY2FsbGJhY2spO1xuICAgICAgaWYgKGNhbGxiYWNrICE9IG51bGwpIHJlcXVlc3Qub24oXCJlcnJvclwiLCBjYWxsYmFjaykub24oXCJsb2FkXCIsIGZ1bmN0aW9uKHhocikgeyBjYWxsYmFjayhudWxsLCB4aHIpOyB9KTtcbiAgICAgIGV2ZW50LmNhbGwoXCJiZWZvcmVzZW5kXCIsIHJlcXVlc3QsIHhocik7XG4gICAgICB4aHIuc2VuZChkYXRhID09IG51bGwgPyBudWxsIDogZGF0YSk7XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9LFxuXG4gICAgYWJvcnQ6IGZ1bmN0aW9uKCkge1xuICAgICAgeGhyLmFib3J0KCk7XG4gICAgICByZXR1cm4gcmVxdWVzdDtcbiAgICB9LFxuXG4gICAgb246IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHZhbHVlID0gZXZlbnQub24uYXBwbHkoZXZlbnQsIGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gdmFsdWUgPT09IGV2ZW50ID8gcmVxdWVzdCA6IHZhbHVlO1xuICAgIH1cbiAgfTtcblxuICBpZiAoY2FsbGJhY2sgIT0gbnVsbCkge1xuICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBjYWxsYmFjazogXCIgKyBjYWxsYmFjayk7XG4gICAgcmV0dXJuIHJlcXVlc3QuZ2V0KGNhbGxiYWNrKTtcbiAgfVxuXG4gIHJldHVybiByZXF1ZXN0O1xufTtcblxuZnVuY3Rpb24gZml4Q2FsbGJhY2soY2FsbGJhY2spIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKGVycm9yLCB4aHIpIHtcbiAgICBjYWxsYmFjayhlcnJvciA9PSBudWxsID8geGhyIDogbnVsbCk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGhhc1Jlc3BvbnNlKHhocikge1xuICB2YXIgdHlwZSA9IHhoci5yZXNwb25zZVR5cGU7XG4gIHJldHVybiB0eXBlICYmIHR5cGUgIT09IFwidGV4dFwiXG4gICAgICA/IHhoci5yZXNwb25zZSAvLyBudWxsIG9uIGVycm9yXG4gICAgICA6IHhoci5yZXNwb25zZVRleHQ7IC8vIFwiXCIgb24gZXJyb3Jcbn1cblxudmFyIHR5cGUgPSBmdW5jdGlvbihkZWZhdWx0TWltZVR5cGUsIHJlc3BvbnNlKSB7XG4gIHJldHVybiBmdW5jdGlvbih1cmwsIGNhbGxiYWNrKSB7XG4gICAgdmFyIHIgPSByZXF1ZXN0KHVybCkubWltZVR5cGUoZGVmYXVsdE1pbWVUeXBlKS5yZXNwb25zZShyZXNwb25zZSk7XG4gICAgaWYgKGNhbGxiYWNrICE9IG51bGwpIHtcbiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBjYWxsYmFjazogXCIgKyBjYWxsYmFjayk7XG4gICAgICByZXR1cm4gci5nZXQoY2FsbGJhY2spO1xuICAgIH1cbiAgICByZXR1cm4gcjtcbiAgfTtcbn07XG5cbnZhciBodG1sID0gdHlwZShcInRleHQvaHRtbFwiLCBmdW5jdGlvbih4aHIpIHtcbiAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZVJhbmdlKCkuY3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KHhoci5yZXNwb25zZVRleHQpO1xufSk7XG5cbnZhciBqc29uID0gdHlwZShcImFwcGxpY2F0aW9uL2pzb25cIiwgZnVuY3Rpb24oeGhyKSB7XG4gIHJldHVybiBKU09OLnBhcnNlKHhoci5yZXNwb25zZVRleHQpO1xufSk7XG5cbnZhciB0ZXh0ID0gdHlwZShcInRleHQvcGxhaW5cIiwgZnVuY3Rpb24oeGhyKSB7XG4gIHJldHVybiB4aHIucmVzcG9uc2VUZXh0O1xufSk7XG5cbnZhciB4bWwgPSB0eXBlKFwiYXBwbGljYXRpb24veG1sXCIsIGZ1bmN0aW9uKHhocikge1xuICB2YXIgeG1sID0geGhyLnJlc3BvbnNlWE1MO1xuICBpZiAoIXhtbCkgdGhyb3cgbmV3IEVycm9yKFwicGFyc2UgZXJyb3JcIik7XG4gIHJldHVybiB4bWw7XG59KTtcblxudmFyIGRzdiA9IGZ1bmN0aW9uKGRlZmF1bHRNaW1lVHlwZSwgcGFyc2UpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHVybCwgcm93LCBjYWxsYmFjaykge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykgY2FsbGJhY2sgPSByb3csIHJvdyA9IG51bGw7XG4gICAgdmFyIHIgPSByZXF1ZXN0KHVybCkubWltZVR5cGUoZGVmYXVsdE1pbWVUeXBlKTtcbiAgICByLnJvdyA9IGZ1bmN0aW9uKF8pIHsgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyByLnJlc3BvbnNlKHJlc3BvbnNlT2YocGFyc2UsIHJvdyA9IF8pKSA6IHJvdzsgfTtcbiAgICByLnJvdyhyb3cpO1xuICAgIHJldHVybiBjYWxsYmFjayA/IHIuZ2V0KGNhbGxiYWNrKSA6IHI7XG4gIH07XG59O1xuXG5mdW5jdGlvbiByZXNwb25zZU9mKHBhcnNlLCByb3cpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKHJlcXVlc3QkJDEpIHtcbiAgICByZXR1cm4gcGFyc2UocmVxdWVzdCQkMS5yZXNwb25zZVRleHQsIHJvdyk7XG4gIH07XG59XG5cbnZhciBjc3YgPSBkc3YoXCJ0ZXh0L2NzdlwiLCBkM0Rzdi5jc3ZQYXJzZSk7XG5cbnZhciB0c3YgPSBkc3YoXCJ0ZXh0L3RhYi1zZXBhcmF0ZWQtdmFsdWVzXCIsIGQzRHN2LnRzdlBhcnNlKTtcblxuZXhwb3J0cy5yZXF1ZXN0ID0gcmVxdWVzdDtcbmV4cG9ydHMuaHRtbCA9IGh0bWw7XG5leHBvcnRzLmpzb24gPSBqc29uO1xuZXhwb3J0cy50ZXh0ID0gdGV4dDtcbmV4cG9ydHMueG1sID0geG1sO1xuZXhwb3J0cy5jc3YgPSBjc3Y7XG5leHBvcnRzLnRzdiA9IHRzdjtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtc2NhbGUvIFZlcnNpb24gMS4wLjcuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgcmVxdWlyZSgnZDMtYXJyYXknKSwgcmVxdWlyZSgnZDMtY29sbGVjdGlvbicpLCByZXF1aXJlKCdkMy1pbnRlcnBvbGF0ZScpLCByZXF1aXJlKCdkMy1mb3JtYXQnKSwgcmVxdWlyZSgnZDMtdGltZScpLCByZXF1aXJlKCdkMy10aW1lLWZvcm1hdCcpLCByZXF1aXJlKCdkMy1jb2xvcicpKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtYXJyYXknLCAnZDMtY29sbGVjdGlvbicsICdkMy1pbnRlcnBvbGF0ZScsICdkMy1mb3JtYXQnLCAnZDMtdGltZScsICdkMy10aW1lLWZvcm1hdCcsICdkMy1jb2xvciddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMykpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMsZDNBcnJheSxkM0NvbGxlY3Rpb24sZDNJbnRlcnBvbGF0ZSxkM0Zvcm1hdCxkM1RpbWUsZDNUaW1lRm9ybWF0LGQzQ29sb3IpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXJyYXkgPSBBcnJheS5wcm90b3R5cGU7XG5cbnZhciBtYXAkMSA9IGFycmF5Lm1hcDtcbnZhciBzbGljZSA9IGFycmF5LnNsaWNlO1xuXG52YXIgaW1wbGljaXQgPSB7bmFtZTogXCJpbXBsaWNpdFwifTtcblxuZnVuY3Rpb24gb3JkaW5hbChyYW5nZSQkMSkge1xuICB2YXIgaW5kZXggPSBkM0NvbGxlY3Rpb24ubWFwKCksXG4gICAgICBkb21haW4gPSBbXSxcbiAgICAgIHVua25vd24gPSBpbXBsaWNpdDtcblxuICByYW5nZSQkMSA9IHJhbmdlJCQxID09IG51bGwgPyBbXSA6IHNsaWNlLmNhbGwocmFuZ2UkJDEpO1xuXG4gIGZ1bmN0aW9uIHNjYWxlKGQpIHtcbiAgICB2YXIga2V5ID0gZCArIFwiXCIsIGkgPSBpbmRleC5nZXQoa2V5KTtcbiAgICBpZiAoIWkpIHtcbiAgICAgIGlmICh1bmtub3duICE9PSBpbXBsaWNpdCkgcmV0dXJuIHVua25vd247XG4gICAgICBpbmRleC5zZXQoa2V5LCBpID0gZG9tYWluLnB1c2goZCkpO1xuICAgIH1cbiAgICByZXR1cm4gcmFuZ2UkJDFbKGkgLSAxKSAlIHJhbmdlJCQxLmxlbmd0aF07XG4gIH1cblxuICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbihfKSB7XG4gICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSByZXR1cm4gZG9tYWluLnNsaWNlKCk7XG4gICAgZG9tYWluID0gW10sIGluZGV4ID0gZDNDb2xsZWN0aW9uLm1hcCgpO1xuICAgIHZhciBpID0gLTEsIG4gPSBfLmxlbmd0aCwgZCwga2V5O1xuICAgIHdoaWxlICgrK2kgPCBuKSBpZiAoIWluZGV4LmhhcyhrZXkgPSAoZCA9IF9baV0pICsgXCJcIikpIGluZGV4LnNldChrZXksIGRvbWFpbi5wdXNoKGQpKTtcbiAgICByZXR1cm4gc2NhbGU7XG4gIH07XG5cbiAgc2NhbGUucmFuZ2UgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFuZ2UkJDEgPSBzbGljZS5jYWxsKF8pLCBzY2FsZSkgOiByYW5nZSQkMS5zbGljZSgpO1xuICB9O1xuXG4gIHNjYWxlLnVua25vd24gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodW5rbm93biA9IF8sIHNjYWxlKSA6IHVua25vd247XG4gIH07XG5cbiAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBvcmRpbmFsKClcbiAgICAgICAgLmRvbWFpbihkb21haW4pXG4gICAgICAgIC5yYW5nZShyYW5nZSQkMSlcbiAgICAgICAgLnVua25vd24odW5rbm93bik7XG4gIH07XG5cbiAgcmV0dXJuIHNjYWxlO1xufVxuXG5mdW5jdGlvbiBiYW5kKCkge1xuICB2YXIgc2NhbGUgPSBvcmRpbmFsKCkudW5rbm93bih1bmRlZmluZWQpLFxuICAgICAgZG9tYWluID0gc2NhbGUuZG9tYWluLFxuICAgICAgb3JkaW5hbFJhbmdlID0gc2NhbGUucmFuZ2UsXG4gICAgICByYW5nZSQkMSA9IFswLCAxXSxcbiAgICAgIHN0ZXAsXG4gICAgICBiYW5kd2lkdGgsXG4gICAgICByb3VuZCA9IGZhbHNlLFxuICAgICAgcGFkZGluZ0lubmVyID0gMCxcbiAgICAgIHBhZGRpbmdPdXRlciA9IDAsXG4gICAgICBhbGlnbiA9IDAuNTtcblxuICBkZWxldGUgc2NhbGUudW5rbm93bjtcblxuICBmdW5jdGlvbiByZXNjYWxlKCkge1xuICAgIHZhciBuID0gZG9tYWluKCkubGVuZ3RoLFxuICAgICAgICByZXZlcnNlID0gcmFuZ2UkJDFbMV0gPCByYW5nZSQkMVswXSxcbiAgICAgICAgc3RhcnQgPSByYW5nZSQkMVtyZXZlcnNlIC0gMF0sXG4gICAgICAgIHN0b3AgPSByYW5nZSQkMVsxIC0gcmV2ZXJzZV07XG4gICAgc3RlcCA9IChzdG9wIC0gc3RhcnQpIC8gTWF0aC5tYXgoMSwgbiAtIHBhZGRpbmdJbm5lciArIHBhZGRpbmdPdXRlciAqIDIpO1xuICAgIGlmIChyb3VuZCkgc3RlcCA9IE1hdGguZmxvb3Ioc3RlcCk7XG4gICAgc3RhcnQgKz0gKHN0b3AgLSBzdGFydCAtIHN0ZXAgKiAobiAtIHBhZGRpbmdJbm5lcikpICogYWxpZ247XG4gICAgYmFuZHdpZHRoID0gc3RlcCAqICgxIC0gcGFkZGluZ0lubmVyKTtcbiAgICBpZiAocm91bmQpIHN0YXJ0ID0gTWF0aC5yb3VuZChzdGFydCksIGJhbmR3aWR0aCA9IE1hdGgucm91bmQoYmFuZHdpZHRoKTtcbiAgICB2YXIgdmFsdWVzID0gZDNBcnJheS5yYW5nZShuKS5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gc3RhcnQgKyBzdGVwICogaTsgfSk7XG4gICAgcmV0dXJuIG9yZGluYWxSYW5nZShyZXZlcnNlID8gdmFsdWVzLnJldmVyc2UoKSA6IHZhbHVlcyk7XG4gIH1cblxuICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluKF8pLCByZXNjYWxlKCkpIDogZG9tYWluKCk7XG4gIH07XG5cbiAgc2NhbGUucmFuZ2UgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocmFuZ2UkJDEgPSBbK19bMF0sICtfWzFdXSwgcmVzY2FsZSgpKSA6IHJhbmdlJCQxLnNsaWNlKCk7XG4gIH07XG5cbiAgc2NhbGUucmFuZ2VSb3VuZCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gcmFuZ2UkJDEgPSBbK19bMF0sICtfWzFdXSwgcm91bmQgPSB0cnVlLCByZXNjYWxlKCk7XG4gIH07XG5cbiAgc2NhbGUuYmFuZHdpZHRoID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGJhbmR3aWR0aDtcbiAgfTtcblxuICBzY2FsZS5zdGVwID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHN0ZXA7XG4gIH07XG5cbiAgc2NhbGUucm91bmQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocm91bmQgPSAhIV8sIHJlc2NhbGUoKSkgOiByb3VuZDtcbiAgfTtcblxuICBzY2FsZS5wYWRkaW5nID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBhZGRpbmdJbm5lciA9IHBhZGRpbmdPdXRlciA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIF8pKSwgcmVzY2FsZSgpKSA6IHBhZGRpbmdJbm5lcjtcbiAgfTtcblxuICBzY2FsZS5wYWRkaW5nSW5uZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkZGluZ0lubmVyID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgXykpLCByZXNjYWxlKCkpIDogcGFkZGluZ0lubmVyO1xuICB9O1xuXG4gIHNjYWxlLnBhZGRpbmdPdXRlciA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChwYWRkaW5nT3V0ZXIgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBfKSksIHJlc2NhbGUoKSkgOiBwYWRkaW5nT3V0ZXI7XG4gIH07XG5cbiAgc2NhbGUuYWxpZ24gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYWxpZ24gPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBfKSksIHJlc2NhbGUoKSkgOiBhbGlnbjtcbiAgfTtcblxuICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGJhbmQoKVxuICAgICAgICAuZG9tYWluKGRvbWFpbigpKVxuICAgICAgICAucmFuZ2UocmFuZ2UkJDEpXG4gICAgICAgIC5yb3VuZChyb3VuZClcbiAgICAgICAgLnBhZGRpbmdJbm5lcihwYWRkaW5nSW5uZXIpXG4gICAgICAgIC5wYWRkaW5nT3V0ZXIocGFkZGluZ091dGVyKVxuICAgICAgICAuYWxpZ24oYWxpZ24pO1xuICB9O1xuXG4gIHJldHVybiByZXNjYWxlKCk7XG59XG5cbmZ1bmN0aW9uIHBvaW50aXNoKHNjYWxlKSB7XG4gIHZhciBjb3B5ID0gc2NhbGUuY29weTtcblxuICBzY2FsZS5wYWRkaW5nID0gc2NhbGUucGFkZGluZ091dGVyO1xuICBkZWxldGUgc2NhbGUucGFkZGluZ0lubmVyO1xuICBkZWxldGUgc2NhbGUucGFkZGluZ091dGVyO1xuXG4gIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gcG9pbnRpc2goY29weSgpKTtcbiAgfTtcblxuICByZXR1cm4gc2NhbGU7XG59XG5cbmZ1bmN0aW9uIHBvaW50KCkge1xuICByZXR1cm4gcG9pbnRpc2goYmFuZCgpLnBhZGRpbmdJbm5lcigxKSk7XG59XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxudmFyIG51bWJlciA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuICt4O1xufTtcblxudmFyIHVuaXQgPSBbMCwgMV07XG5cbmZ1bmN0aW9uIGRlaW50ZXJwb2xhdGVMaW5lYXIoYSwgYikge1xuICByZXR1cm4gKGIgLT0gKGEgPSArYSkpXG4gICAgICA/IGZ1bmN0aW9uKHgpIHsgcmV0dXJuICh4IC0gYSkgLyBiOyB9XG4gICAgICA6IGNvbnN0YW50KGIpO1xufVxuXG5mdW5jdGlvbiBkZWludGVycG9sYXRlQ2xhbXAoZGVpbnRlcnBvbGF0ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgIHZhciBkID0gZGVpbnRlcnBvbGF0ZShhID0gK2EsIGIgPSArYik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHgpIHsgcmV0dXJuIHggPD0gYSA/IDAgOiB4ID49IGIgPyAxIDogZCh4KTsgfTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVpbnRlcnBvbGF0ZUNsYW1wKHJlaW50ZXJwb2xhdGUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgciA9IHJlaW50ZXJwb2xhdGUoYSA9ICthLCBiID0gK2IpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7IHJldHVybiB0IDw9IDAgPyBhIDogdCA+PSAxID8gYiA6IHIodCk7IH07XG4gIH07XG59XG5cbmZ1bmN0aW9uIGJpbWFwKGRvbWFpbiwgcmFuZ2UkJDEsIGRlaW50ZXJwb2xhdGUsIHJlaW50ZXJwb2xhdGUpIHtcbiAgdmFyIGQwID0gZG9tYWluWzBdLCBkMSA9IGRvbWFpblsxXSwgcjAgPSByYW5nZSQkMVswXSwgcjEgPSByYW5nZSQkMVsxXTtcbiAgaWYgKGQxIDwgZDApIGQwID0gZGVpbnRlcnBvbGF0ZShkMSwgZDApLCByMCA9IHJlaW50ZXJwb2xhdGUocjEsIHIwKTtcbiAgZWxzZSBkMCA9IGRlaW50ZXJwb2xhdGUoZDAsIGQxKSwgcjAgPSByZWludGVycG9sYXRlKHIwLCByMSk7XG4gIHJldHVybiBmdW5jdGlvbih4KSB7IHJldHVybiByMChkMCh4KSk7IH07XG59XG5cbmZ1bmN0aW9uIHBvbHltYXAoZG9tYWluLCByYW5nZSQkMSwgZGVpbnRlcnBvbGF0ZSwgcmVpbnRlcnBvbGF0ZSkge1xuICB2YXIgaiA9IE1hdGgubWluKGRvbWFpbi5sZW5ndGgsIHJhbmdlJCQxLmxlbmd0aCkgLSAxLFxuICAgICAgZCA9IG5ldyBBcnJheShqKSxcbiAgICAgIHIgPSBuZXcgQXJyYXkoaiksXG4gICAgICBpID0gLTE7XG5cbiAgLy8gUmV2ZXJzZSBkZXNjZW5kaW5nIGRvbWFpbnMuXG4gIGlmIChkb21haW5bal0gPCBkb21haW5bMF0pIHtcbiAgICBkb21haW4gPSBkb21haW4uc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgcmFuZ2UkJDEgPSByYW5nZSQkMS5zbGljZSgpLnJldmVyc2UoKTtcbiAgfVxuXG4gIHdoaWxlICgrK2kgPCBqKSB7XG4gICAgZFtpXSA9IGRlaW50ZXJwb2xhdGUoZG9tYWluW2ldLCBkb21haW5baSArIDFdKTtcbiAgICByW2ldID0gcmVpbnRlcnBvbGF0ZShyYW5nZSQkMVtpXSwgcmFuZ2UkJDFbaSArIDFdKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbih4KSB7XG4gICAgdmFyIGkgPSBkM0FycmF5LmJpc2VjdChkb21haW4sIHgsIDEsIGopIC0gMTtcbiAgICByZXR1cm4gcltpXShkW2ldKHgpKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gY29weShzb3VyY2UsIHRhcmdldCkge1xuICByZXR1cm4gdGFyZ2V0XG4gICAgICAuZG9tYWluKHNvdXJjZS5kb21haW4oKSlcbiAgICAgIC5yYW5nZShzb3VyY2UucmFuZ2UoKSlcbiAgICAgIC5pbnRlcnBvbGF0ZShzb3VyY2UuaW50ZXJwb2xhdGUoKSlcbiAgICAgIC5jbGFtcChzb3VyY2UuY2xhbXAoKSk7XG59XG5cbi8vIGRlaW50ZXJwb2xhdGUoYSwgYikoeCkgdGFrZXMgYSBkb21haW4gdmFsdWUgeCBpbiBbYSxiXSBhbmQgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBwYXJhbWV0ZXIgdCBpbiBbMCwxXS5cbi8vIHJlaW50ZXJwb2xhdGUoYSwgYikodCkgdGFrZXMgYSBwYXJhbWV0ZXIgdCBpbiBbMCwxXSBhbmQgcmV0dXJucyB0aGUgY29ycmVzcG9uZGluZyBkb21haW4gdmFsdWUgeCBpbiBbYSxiXS5cbmZ1bmN0aW9uIGNvbnRpbnVvdXMoZGVpbnRlcnBvbGF0ZSwgcmVpbnRlcnBvbGF0ZSkge1xuICB2YXIgZG9tYWluID0gdW5pdCxcbiAgICAgIHJhbmdlJCQxID0gdW5pdCxcbiAgICAgIGludGVycG9sYXRlJCQxID0gZDNJbnRlcnBvbGF0ZS5pbnRlcnBvbGF0ZSxcbiAgICAgIGNsYW1wID0gZmFsc2UsXG4gICAgICBwaWVjZXdpc2UsXG4gICAgICBvdXRwdXQsXG4gICAgICBpbnB1dDtcblxuICBmdW5jdGlvbiByZXNjYWxlKCkge1xuICAgIHBpZWNld2lzZSA9IE1hdGgubWluKGRvbWFpbi5sZW5ndGgsIHJhbmdlJCQxLmxlbmd0aCkgPiAyID8gcG9seW1hcCA6IGJpbWFwO1xuICAgIG91dHB1dCA9IGlucHV0ID0gbnVsbDtcbiAgICByZXR1cm4gc2NhbGU7XG4gIH1cblxuICBmdW5jdGlvbiBzY2FsZSh4KSB7XG4gICAgcmV0dXJuIChvdXRwdXQgfHwgKG91dHB1dCA9IHBpZWNld2lzZShkb21haW4sIHJhbmdlJCQxLCBjbGFtcCA/IGRlaW50ZXJwb2xhdGVDbGFtcChkZWludGVycG9sYXRlKSA6IGRlaW50ZXJwb2xhdGUsIGludGVycG9sYXRlJCQxKSkpKCt4KTtcbiAgfVxuXG4gIHNjYWxlLmludmVydCA9IGZ1bmN0aW9uKHkpIHtcbiAgICByZXR1cm4gKGlucHV0IHx8IChpbnB1dCA9IHBpZWNld2lzZShyYW5nZSQkMSwgZG9tYWluLCBkZWludGVycG9sYXRlTGluZWFyLCBjbGFtcCA/IHJlaW50ZXJwb2xhdGVDbGFtcChyZWludGVycG9sYXRlKSA6IHJlaW50ZXJwb2xhdGUpKSkoK3kpO1xuICB9O1xuXG4gIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkb21haW4gPSBtYXAkMS5jYWxsKF8sIG51bWJlciksIHJlc2NhbGUoKSkgOiBkb21haW4uc2xpY2UoKTtcbiAgfTtcblxuICBzY2FsZS5yYW5nZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyYW5nZSQkMSA9IHNsaWNlLmNhbGwoXyksIHJlc2NhbGUoKSkgOiByYW5nZSQkMS5zbGljZSgpO1xuICB9O1xuXG4gIHNjYWxlLnJhbmdlUm91bmQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIHJhbmdlJCQxID0gc2xpY2UuY2FsbChfKSwgaW50ZXJwb2xhdGUkJDEgPSBkM0ludGVycG9sYXRlLmludGVycG9sYXRlUm91bmQsIHJlc2NhbGUoKTtcbiAgfTtcblxuICBzY2FsZS5jbGFtcCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjbGFtcCA9ICEhXywgcmVzY2FsZSgpKSA6IGNsYW1wO1xuICB9O1xuXG4gIHNjYWxlLmludGVycG9sYXRlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGludGVycG9sYXRlJCQxID0gXywgcmVzY2FsZSgpKSA6IGludGVycG9sYXRlJCQxO1xuICB9O1xuXG4gIHJldHVybiByZXNjYWxlKCk7XG59XG5cbnZhciB0aWNrRm9ybWF0ID0gZnVuY3Rpb24oZG9tYWluLCBjb3VudCwgc3BlY2lmaWVyKSB7XG4gIHZhciBzdGFydCA9IGRvbWFpblswXSxcbiAgICAgIHN0b3AgPSBkb21haW5bZG9tYWluLmxlbmd0aCAtIDFdLFxuICAgICAgc3RlcCA9IGQzQXJyYXkudGlja1N0ZXAoc3RhcnQsIHN0b3AsIGNvdW50ID09IG51bGwgPyAxMCA6IGNvdW50KSxcbiAgICAgIHByZWNpc2lvbjtcbiAgc3BlY2lmaWVyID0gZDNGb3JtYXQuZm9ybWF0U3BlY2lmaWVyKHNwZWNpZmllciA9PSBudWxsID8gXCIsZlwiIDogc3BlY2lmaWVyKTtcbiAgc3dpdGNoIChzcGVjaWZpZXIudHlwZSkge1xuICAgIGNhc2UgXCJzXCI6IHtcbiAgICAgIHZhciB2YWx1ZSA9IE1hdGgubWF4KE1hdGguYWJzKHN0YXJ0KSwgTWF0aC5hYnMoc3RvcCkpO1xuICAgICAgaWYgKHNwZWNpZmllci5wcmVjaXNpb24gPT0gbnVsbCAmJiAhaXNOYU4ocHJlY2lzaW9uID0gZDNGb3JtYXQucHJlY2lzaW9uUHJlZml4KHN0ZXAsIHZhbHVlKSkpIHNwZWNpZmllci5wcmVjaXNpb24gPSBwcmVjaXNpb247XG4gICAgICByZXR1cm4gZDNGb3JtYXQuZm9ybWF0UHJlZml4KHNwZWNpZmllciwgdmFsdWUpO1xuICAgIH1cbiAgICBjYXNlIFwiXCI6XG4gICAgY2FzZSBcImVcIjpcbiAgICBjYXNlIFwiZ1wiOlxuICAgIGNhc2UgXCJwXCI6XG4gICAgY2FzZSBcInJcIjoge1xuICAgICAgaWYgKHNwZWNpZmllci5wcmVjaXNpb24gPT0gbnVsbCAmJiAhaXNOYU4ocHJlY2lzaW9uID0gZDNGb3JtYXQucHJlY2lzaW9uUm91bmQoc3RlcCwgTWF0aC5tYXgoTWF0aC5hYnMoc3RhcnQpLCBNYXRoLmFicyhzdG9wKSkpKSkgc3BlY2lmaWVyLnByZWNpc2lvbiA9IHByZWNpc2lvbiAtIChzcGVjaWZpZXIudHlwZSA9PT0gXCJlXCIpO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIGNhc2UgXCJmXCI6XG4gICAgY2FzZSBcIiVcIjoge1xuICAgICAgaWYgKHNwZWNpZmllci5wcmVjaXNpb24gPT0gbnVsbCAmJiAhaXNOYU4ocHJlY2lzaW9uID0gZDNGb3JtYXQucHJlY2lzaW9uRml4ZWQoc3RlcCkpKSBzcGVjaWZpZXIucHJlY2lzaW9uID0gcHJlY2lzaW9uIC0gKHNwZWNpZmllci50eXBlID09PSBcIiVcIikgKiAyO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBkM0Zvcm1hdC5mb3JtYXQoc3BlY2lmaWVyKTtcbn07XG5cbmZ1bmN0aW9uIGxpbmVhcmlzaChzY2FsZSkge1xuICB2YXIgZG9tYWluID0gc2NhbGUuZG9tYWluO1xuXG4gIHNjYWxlLnRpY2tzID0gZnVuY3Rpb24oY291bnQpIHtcbiAgICB2YXIgZCA9IGRvbWFpbigpO1xuICAgIHJldHVybiBkM0FycmF5LnRpY2tzKGRbMF0sIGRbZC5sZW5ndGggLSAxXSwgY291bnQgPT0gbnVsbCA/IDEwIDogY291bnQpO1xuICB9O1xuXG4gIHNjYWxlLnRpY2tGb3JtYXQgPSBmdW5jdGlvbihjb3VudCwgc3BlY2lmaWVyKSB7XG4gICAgcmV0dXJuIHRpY2tGb3JtYXQoZG9tYWluKCksIGNvdW50LCBzcGVjaWZpZXIpO1xuICB9O1xuXG4gIHNjYWxlLm5pY2UgPSBmdW5jdGlvbihjb3VudCkge1xuICAgIGlmIChjb3VudCA9PSBudWxsKSBjb3VudCA9IDEwO1xuXG4gICAgdmFyIGQgPSBkb21haW4oKSxcbiAgICAgICAgaTAgPSAwLFxuICAgICAgICBpMSA9IGQubGVuZ3RoIC0gMSxcbiAgICAgICAgc3RhcnQgPSBkW2kwXSxcbiAgICAgICAgc3RvcCA9IGRbaTFdLFxuICAgICAgICBzdGVwO1xuXG4gICAgaWYgKHN0b3AgPCBzdGFydCkge1xuICAgICAgc3RlcCA9IHN0YXJ0LCBzdGFydCA9IHN0b3AsIHN0b3AgPSBzdGVwO1xuICAgICAgc3RlcCA9IGkwLCBpMCA9IGkxLCBpMSA9IHN0ZXA7XG4gICAgfVxuXG4gICAgc3RlcCA9IGQzQXJyYXkudGlja0luY3JlbWVudChzdGFydCwgc3RvcCwgY291bnQpO1xuXG4gICAgaWYgKHN0ZXAgPiAwKSB7XG4gICAgICBzdGFydCA9IE1hdGguZmxvb3Ioc3RhcnQgLyBzdGVwKSAqIHN0ZXA7XG4gICAgICBzdG9wID0gTWF0aC5jZWlsKHN0b3AgLyBzdGVwKSAqIHN0ZXA7XG4gICAgICBzdGVwID0gZDNBcnJheS50aWNrSW5jcmVtZW50KHN0YXJ0LCBzdG9wLCBjb3VudCk7XG4gICAgfSBlbHNlIGlmIChzdGVwIDwgMCkge1xuICAgICAgc3RhcnQgPSBNYXRoLmNlaWwoc3RhcnQgKiBzdGVwKSAvIHN0ZXA7XG4gICAgICBzdG9wID0gTWF0aC5mbG9vcihzdG9wICogc3RlcCkgLyBzdGVwO1xuICAgICAgc3RlcCA9IGQzQXJyYXkudGlja0luY3JlbWVudChzdGFydCwgc3RvcCwgY291bnQpO1xuICAgIH1cblxuICAgIGlmIChzdGVwID4gMCkge1xuICAgICAgZFtpMF0gPSBNYXRoLmZsb29yKHN0YXJ0IC8gc3RlcCkgKiBzdGVwO1xuICAgICAgZFtpMV0gPSBNYXRoLmNlaWwoc3RvcCAvIHN0ZXApICogc3RlcDtcbiAgICAgIGRvbWFpbihkKTtcbiAgICB9IGVsc2UgaWYgKHN0ZXAgPCAwKSB7XG4gICAgICBkW2kwXSA9IE1hdGguY2VpbChzdGFydCAqIHN0ZXApIC8gc3RlcDtcbiAgICAgIGRbaTFdID0gTWF0aC5mbG9vcihzdG9wICogc3RlcCkgLyBzdGVwO1xuICAgICAgZG9tYWluKGQpO1xuICAgIH1cblxuICAgIHJldHVybiBzY2FsZTtcbiAgfTtcblxuICByZXR1cm4gc2NhbGU7XG59XG5cbmZ1bmN0aW9uIGxpbmVhcigpIHtcbiAgdmFyIHNjYWxlID0gY29udGludW91cyhkZWludGVycG9sYXRlTGluZWFyLCBkM0ludGVycG9sYXRlLmludGVycG9sYXRlTnVtYmVyKTtcblxuICBzY2FsZS5jb3B5ID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGNvcHkoc2NhbGUsIGxpbmVhcigpKTtcbiAgfTtcblxuICByZXR1cm4gbGluZWFyaXNoKHNjYWxlKTtcbn1cblxuZnVuY3Rpb24gaWRlbnRpdHkoKSB7XG4gIHZhciBkb21haW4gPSBbMCwgMV07XG5cbiAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgIHJldHVybiAreDtcbiAgfVxuXG4gIHNjYWxlLmludmVydCA9IHNjYWxlO1xuXG4gIHNjYWxlLmRvbWFpbiA9IHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRvbWFpbiA9IG1hcCQxLmNhbGwoXywgbnVtYmVyKSwgc2NhbGUpIDogZG9tYWluLnNsaWNlKCk7XG4gIH07XG5cbiAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBpZGVudGl0eSgpLmRvbWFpbihkb21haW4pO1xuICB9O1xuXG4gIHJldHVybiBsaW5lYXJpc2goc2NhbGUpO1xufVxuXG52YXIgbmljZSA9IGZ1bmN0aW9uKGRvbWFpbiwgaW50ZXJ2YWwpIHtcbiAgZG9tYWluID0gZG9tYWluLnNsaWNlKCk7XG5cbiAgdmFyIGkwID0gMCxcbiAgICAgIGkxID0gZG9tYWluLmxlbmd0aCAtIDEsXG4gICAgICB4MCA9IGRvbWFpbltpMF0sXG4gICAgICB4MSA9IGRvbWFpbltpMV0sXG4gICAgICB0O1xuXG4gIGlmICh4MSA8IHgwKSB7XG4gICAgdCA9IGkwLCBpMCA9IGkxLCBpMSA9IHQ7XG4gICAgdCA9IHgwLCB4MCA9IHgxLCB4MSA9IHQ7XG4gIH1cblxuICBkb21haW5baTBdID0gaW50ZXJ2YWwuZmxvb3IoeDApO1xuICBkb21haW5baTFdID0gaW50ZXJ2YWwuY2VpbCh4MSk7XG4gIHJldHVybiBkb21haW47XG59O1xuXG5mdW5jdGlvbiBkZWludGVycG9sYXRlKGEsIGIpIHtcbiAgcmV0dXJuIChiID0gTWF0aC5sb2coYiAvIGEpKVxuICAgICAgPyBmdW5jdGlvbih4KSB7IHJldHVybiBNYXRoLmxvZyh4IC8gYSkgLyBiOyB9XG4gICAgICA6IGNvbnN0YW50KGIpO1xufVxuXG5mdW5jdGlvbiByZWludGVycG9sYXRlKGEsIGIpIHtcbiAgcmV0dXJuIGEgPCAwXG4gICAgICA/IGZ1bmN0aW9uKHQpIHsgcmV0dXJuIC1NYXRoLnBvdygtYiwgdCkgKiBNYXRoLnBvdygtYSwgMSAtIHQpOyB9XG4gICAgICA6IGZ1bmN0aW9uKHQpIHsgcmV0dXJuIE1hdGgucG93KGIsIHQpICogTWF0aC5wb3coYSwgMSAtIHQpOyB9O1xufVxuXG5mdW5jdGlvbiBwb3cxMCh4KSB7XG4gIHJldHVybiBpc0Zpbml0ZSh4KSA/ICsoXCIxZVwiICsgeCkgOiB4IDwgMCA/IDAgOiB4O1xufVxuXG5mdW5jdGlvbiBwb3dwKGJhc2UpIHtcbiAgcmV0dXJuIGJhc2UgPT09IDEwID8gcG93MTBcbiAgICAgIDogYmFzZSA9PT0gTWF0aC5FID8gTWF0aC5leHBcbiAgICAgIDogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5wb3coYmFzZSwgeCk7IH07XG59XG5cbmZ1bmN0aW9uIGxvZ3AoYmFzZSkge1xuICByZXR1cm4gYmFzZSA9PT0gTWF0aC5FID8gTWF0aC5sb2dcbiAgICAgIDogYmFzZSA9PT0gMTAgJiYgTWF0aC5sb2cxMFxuICAgICAgfHwgYmFzZSA9PT0gMiAmJiBNYXRoLmxvZzJcbiAgICAgIHx8IChiYXNlID0gTWF0aC5sb2coYmFzZSksIGZ1bmN0aW9uKHgpIHsgcmV0dXJuIE1hdGgubG9nKHgpIC8gYmFzZTsgfSk7XG59XG5cbmZ1bmN0aW9uIHJlZmxlY3QoZikge1xuICByZXR1cm4gZnVuY3Rpb24oeCkge1xuICAgIHJldHVybiAtZigteCk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGxvZygpIHtcbiAgdmFyIHNjYWxlID0gY29udGludW91cyhkZWludGVycG9sYXRlLCByZWludGVycG9sYXRlKS5kb21haW4oWzEsIDEwXSksXG4gICAgICBkb21haW4gPSBzY2FsZS5kb21haW4sXG4gICAgICBiYXNlID0gMTAsXG4gICAgICBsb2dzID0gbG9ncCgxMCksXG4gICAgICBwb3dzID0gcG93cCgxMCk7XG5cbiAgZnVuY3Rpb24gcmVzY2FsZSgpIHtcbiAgICBsb2dzID0gbG9ncChiYXNlKSwgcG93cyA9IHBvd3AoYmFzZSk7XG4gICAgaWYgKGRvbWFpbigpWzBdIDwgMCkgbG9ncyA9IHJlZmxlY3QobG9ncyksIHBvd3MgPSByZWZsZWN0KHBvd3MpO1xuICAgIHJldHVybiBzY2FsZTtcbiAgfVxuXG4gIHNjYWxlLmJhc2UgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoYmFzZSA9ICtfLCByZXNjYWxlKCkpIDogYmFzZTtcbiAgfTtcblxuICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZG9tYWluKF8pLCByZXNjYWxlKCkpIDogZG9tYWluKCk7XG4gIH07XG5cbiAgc2NhbGUudGlja3MgPSBmdW5jdGlvbihjb3VudCkge1xuICAgIHZhciBkID0gZG9tYWluKCksXG4gICAgICAgIHUgPSBkWzBdLFxuICAgICAgICB2ID0gZFtkLmxlbmd0aCAtIDFdLFxuICAgICAgICByO1xuXG4gICAgaWYgKHIgPSB2IDwgdSkgaSA9IHUsIHUgPSB2LCB2ID0gaTtcblxuICAgIHZhciBpID0gbG9ncyh1KSxcbiAgICAgICAgaiA9IGxvZ3ModiksXG4gICAgICAgIHAsXG4gICAgICAgIGssXG4gICAgICAgIHQsXG4gICAgICAgIG4gPSBjb3VudCA9PSBudWxsID8gMTAgOiArY291bnQsXG4gICAgICAgIHogPSBbXTtcblxuICAgIGlmICghKGJhc2UgJSAxKSAmJiBqIC0gaSA8IG4pIHtcbiAgICAgIGkgPSBNYXRoLnJvdW5kKGkpIC0gMSwgaiA9IE1hdGgucm91bmQoaikgKyAxO1xuICAgICAgaWYgKHUgPiAwKSBmb3IgKDsgaSA8IGo7ICsraSkge1xuICAgICAgICBmb3IgKGsgPSAxLCBwID0gcG93cyhpKTsgayA8IGJhc2U7ICsraykge1xuICAgICAgICAgIHQgPSBwICogaztcbiAgICAgICAgICBpZiAodCA8IHUpIGNvbnRpbnVlO1xuICAgICAgICAgIGlmICh0ID4gdikgYnJlYWs7XG4gICAgICAgICAgei5wdXNoKHQpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgZm9yICg7IGkgPCBqOyArK2kpIHtcbiAgICAgICAgZm9yIChrID0gYmFzZSAtIDEsIHAgPSBwb3dzKGkpOyBrID49IDE7IC0taykge1xuICAgICAgICAgIHQgPSBwICogaztcbiAgICAgICAgICBpZiAodCA8IHUpIGNvbnRpbnVlO1xuICAgICAgICAgIGlmICh0ID4gdikgYnJlYWs7XG4gICAgICAgICAgei5wdXNoKHQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHogPSBkM0FycmF5LnRpY2tzKGksIGosIE1hdGgubWluKGogLSBpLCBuKSkubWFwKHBvd3MpO1xuICAgIH1cblxuICAgIHJldHVybiByID8gei5yZXZlcnNlKCkgOiB6O1xuICB9O1xuXG4gIHNjYWxlLnRpY2tGb3JtYXQgPSBmdW5jdGlvbihjb3VudCwgc3BlY2lmaWVyKSB7XG4gICAgaWYgKHNwZWNpZmllciA9PSBudWxsKSBzcGVjaWZpZXIgPSBiYXNlID09PSAxMCA/IFwiLjBlXCIgOiBcIixcIjtcbiAgICBpZiAodHlwZW9mIHNwZWNpZmllciAhPT0gXCJmdW5jdGlvblwiKSBzcGVjaWZpZXIgPSBkM0Zvcm1hdC5mb3JtYXQoc3BlY2lmaWVyKTtcbiAgICBpZiAoY291bnQgPT09IEluZmluaXR5KSByZXR1cm4gc3BlY2lmaWVyO1xuICAgIGlmIChjb3VudCA9PSBudWxsKSBjb3VudCA9IDEwO1xuICAgIHZhciBrID0gTWF0aC5tYXgoMSwgYmFzZSAqIGNvdW50IC8gc2NhbGUudGlja3MoKS5sZW5ndGgpOyAvLyBUT0RPIGZhc3QgZXN0aW1hdGU/XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGQpIHtcbiAgICAgIHZhciBpID0gZCAvIHBvd3MoTWF0aC5yb3VuZChsb2dzKGQpKSk7XG4gICAgICBpZiAoaSAqIGJhc2UgPCBiYXNlIC0gMC41KSBpICo9IGJhc2U7XG4gICAgICByZXR1cm4gaSA8PSBrID8gc3BlY2lmaWVyKGQpIDogXCJcIjtcbiAgICB9O1xuICB9O1xuXG4gIHNjYWxlLm5pY2UgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZG9tYWluKG5pY2UoZG9tYWluKCksIHtcbiAgICAgIGZsb29yOiBmdW5jdGlvbih4KSB7IHJldHVybiBwb3dzKE1hdGguZmxvb3IobG9ncyh4KSkpOyB9LFxuICAgICAgY2VpbDogZnVuY3Rpb24oeCkgeyByZXR1cm4gcG93cyhNYXRoLmNlaWwobG9ncyh4KSkpOyB9XG4gICAgfSkpO1xuICB9O1xuXG4gIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gY29weShzY2FsZSwgbG9nKCkuYmFzZShiYXNlKSk7XG4gIH07XG5cbiAgcmV0dXJuIHNjYWxlO1xufVxuXG5mdW5jdGlvbiByYWlzZSh4LCBleHBvbmVudCkge1xuICByZXR1cm4geCA8IDAgPyAtTWF0aC5wb3coLXgsIGV4cG9uZW50KSA6IE1hdGgucG93KHgsIGV4cG9uZW50KTtcbn1cblxuZnVuY3Rpb24gcG93KCkge1xuICB2YXIgZXhwb25lbnQgPSAxLFxuICAgICAgc2NhbGUgPSBjb250aW51b3VzKGRlaW50ZXJwb2xhdGUsIHJlaW50ZXJwb2xhdGUpLFxuICAgICAgZG9tYWluID0gc2NhbGUuZG9tYWluO1xuXG4gIGZ1bmN0aW9uIGRlaW50ZXJwb2xhdGUoYSwgYikge1xuICAgIHJldHVybiAoYiA9IHJhaXNlKGIsIGV4cG9uZW50KSAtIChhID0gcmFpc2UoYSwgZXhwb25lbnQpKSlcbiAgICAgICAgPyBmdW5jdGlvbih4KSB7IHJldHVybiAocmFpc2UoeCwgZXhwb25lbnQpIC0gYSkgLyBiOyB9XG4gICAgICAgIDogY29uc3RhbnQoYik7XG4gIH1cblxuICBmdW5jdGlvbiByZWludGVycG9sYXRlKGEsIGIpIHtcbiAgICBiID0gcmFpc2UoYiwgZXhwb25lbnQpIC0gKGEgPSByYWlzZShhLCBleHBvbmVudCkpO1xuICAgIHJldHVybiBmdW5jdGlvbih0KSB7IHJldHVybiByYWlzZShhICsgYiAqIHQsIDEgLyBleHBvbmVudCk7IH07XG4gIH1cblxuICBzY2FsZS5leHBvbmVudCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChleHBvbmVudCA9ICtfLCBkb21haW4oZG9tYWluKCkpKSA6IGV4cG9uZW50O1xuICB9O1xuXG4gIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gY29weShzY2FsZSwgcG93KCkuZXhwb25lbnQoZXhwb25lbnQpKTtcbiAgfTtcblxuICByZXR1cm4gbGluZWFyaXNoKHNjYWxlKTtcbn1cblxuZnVuY3Rpb24gc3FydCgpIHtcbiAgcmV0dXJuIHBvdygpLmV4cG9uZW50KDAuNSk7XG59XG5cbmZ1bmN0aW9uIHF1YW50aWxlJDEoKSB7XG4gIHZhciBkb21haW4gPSBbXSxcbiAgICAgIHJhbmdlJCQxID0gW10sXG4gICAgICB0aHJlc2hvbGRzID0gW107XG5cbiAgZnVuY3Rpb24gcmVzY2FsZSgpIHtcbiAgICB2YXIgaSA9IDAsIG4gPSBNYXRoLm1heCgxLCByYW5nZSQkMS5sZW5ndGgpO1xuICAgIHRocmVzaG9sZHMgPSBuZXcgQXJyYXkobiAtIDEpO1xuICAgIHdoaWxlICgrK2kgPCBuKSB0aHJlc2hvbGRzW2kgLSAxXSA9IGQzQXJyYXkucXVhbnRpbGUoZG9tYWluLCBpIC8gbik7XG4gICAgcmV0dXJuIHNjYWxlO1xuICB9XG5cbiAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgIGlmICghaXNOYU4oeCA9ICt4KSkgcmV0dXJuIHJhbmdlJCQxW2QzQXJyYXkuYmlzZWN0KHRocmVzaG9sZHMsIHgpXTtcbiAgfVxuXG4gIHNjYWxlLmludmVydEV4dGVudCA9IGZ1bmN0aW9uKHkpIHtcbiAgICB2YXIgaSA9IHJhbmdlJCQxLmluZGV4T2YoeSk7XG4gICAgcmV0dXJuIGkgPCAwID8gW05hTiwgTmFOXSA6IFtcbiAgICAgIGkgPiAwID8gdGhyZXNob2xkc1tpIC0gMV0gOiBkb21haW5bMF0sXG4gICAgICBpIDwgdGhyZXNob2xkcy5sZW5ndGggPyB0aHJlc2hvbGRzW2ldIDogZG9tYWluW2RvbWFpbi5sZW5ndGggLSAxXVxuICAgIF07XG4gIH07XG5cbiAgc2NhbGUuZG9tYWluID0gZnVuY3Rpb24oXykge1xuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkgcmV0dXJuIGRvbWFpbi5zbGljZSgpO1xuICAgIGRvbWFpbiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gXy5sZW5ndGgsIGQ7IGkgPCBuOyArK2kpIGlmIChkID0gX1tpXSwgZCAhPSBudWxsICYmICFpc05hTihkID0gK2QpKSBkb21haW4ucHVzaChkKTtcbiAgICBkb21haW4uc29ydChkM0FycmF5LmFzY2VuZGluZyk7XG4gICAgcmV0dXJuIHJlc2NhbGUoKTtcbiAgfTtcblxuICBzY2FsZS5yYW5nZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChyYW5nZSQkMSA9IHNsaWNlLmNhbGwoXyksIHJlc2NhbGUoKSkgOiByYW5nZSQkMS5zbGljZSgpO1xuICB9O1xuXG4gIHNjYWxlLnF1YW50aWxlcyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aHJlc2hvbGRzLnNsaWNlKCk7XG4gIH07XG5cbiAgc2NhbGUuY29weSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBxdWFudGlsZSQxKClcbiAgICAgICAgLmRvbWFpbihkb21haW4pXG4gICAgICAgIC5yYW5nZShyYW5nZSQkMSk7XG4gIH07XG5cbiAgcmV0dXJuIHNjYWxlO1xufVxuXG5mdW5jdGlvbiBxdWFudGl6ZSgpIHtcbiAgdmFyIHgwID0gMCxcbiAgICAgIHgxID0gMSxcbiAgICAgIG4gPSAxLFxuICAgICAgZG9tYWluID0gWzAuNV0sXG4gICAgICByYW5nZSQkMSA9IFswLCAxXTtcblxuICBmdW5jdGlvbiBzY2FsZSh4KSB7XG4gICAgaWYgKHggPD0geCkgcmV0dXJuIHJhbmdlJCQxW2QzQXJyYXkuYmlzZWN0KGRvbWFpbiwgeCwgMCwgbildO1xuICB9XG5cbiAgZnVuY3Rpb24gcmVzY2FsZSgpIHtcbiAgICB2YXIgaSA9IC0xO1xuICAgIGRvbWFpbiA9IG5ldyBBcnJheShuKTtcbiAgICB3aGlsZSAoKytpIDwgbikgZG9tYWluW2ldID0gKChpICsgMSkgKiB4MSAtIChpIC0gbikgKiB4MCkgLyAobiArIDEpO1xuICAgIHJldHVybiBzY2FsZTtcbiAgfVxuXG4gIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4MCA9ICtfWzBdLCB4MSA9ICtfWzFdLCByZXNjYWxlKCkpIDogW3gwLCB4MV07XG4gIH07XG5cbiAgc2NhbGUucmFuZ2UgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAobiA9IChyYW5nZSQkMSA9IHNsaWNlLmNhbGwoXykpLmxlbmd0aCAtIDEsIHJlc2NhbGUoKSkgOiByYW5nZSQkMS5zbGljZSgpO1xuICB9O1xuXG4gIHNjYWxlLmludmVydEV4dGVudCA9IGZ1bmN0aW9uKHkpIHtcbiAgICB2YXIgaSA9IHJhbmdlJCQxLmluZGV4T2YoeSk7XG4gICAgcmV0dXJuIGkgPCAwID8gW05hTiwgTmFOXVxuICAgICAgICA6IGkgPCAxID8gW3gwLCBkb21haW5bMF1dXG4gICAgICAgIDogaSA+PSBuID8gW2RvbWFpbltuIC0gMV0sIHgxXVxuICAgICAgICA6IFtkb21haW5baSAtIDFdLCBkb21haW5baV1dO1xuICB9O1xuXG4gIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gcXVhbnRpemUoKVxuICAgICAgICAuZG9tYWluKFt4MCwgeDFdKVxuICAgICAgICAucmFuZ2UocmFuZ2UkJDEpO1xuICB9O1xuXG4gIHJldHVybiBsaW5lYXJpc2goc2NhbGUpO1xufVxuXG5mdW5jdGlvbiB0aHJlc2hvbGQoKSB7XG4gIHZhciBkb21haW4gPSBbMC41XSxcbiAgICAgIHJhbmdlJCQxID0gWzAsIDFdLFxuICAgICAgbiA9IDE7XG5cbiAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgIGlmICh4IDw9IHgpIHJldHVybiByYW5nZSQkMVtkM0FycmF5LmJpc2VjdChkb21haW4sIHgsIDAsIG4pXTtcbiAgfVxuXG4gIHNjYWxlLmRvbWFpbiA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChkb21haW4gPSBzbGljZS5jYWxsKF8pLCBuID0gTWF0aC5taW4oZG9tYWluLmxlbmd0aCwgcmFuZ2UkJDEubGVuZ3RoIC0gMSksIHNjYWxlKSA6IGRvbWFpbi5zbGljZSgpO1xuICB9O1xuXG4gIHNjYWxlLnJhbmdlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHJhbmdlJCQxID0gc2xpY2UuY2FsbChfKSwgbiA9IE1hdGgubWluKGRvbWFpbi5sZW5ndGgsIHJhbmdlJCQxLmxlbmd0aCAtIDEpLCBzY2FsZSkgOiByYW5nZSQkMS5zbGljZSgpO1xuICB9O1xuXG4gIHNjYWxlLmludmVydEV4dGVudCA9IGZ1bmN0aW9uKHkpIHtcbiAgICB2YXIgaSA9IHJhbmdlJCQxLmluZGV4T2YoeSk7XG4gICAgcmV0dXJuIFtkb21haW5baSAtIDFdLCBkb21haW5baV1dO1xuICB9O1xuXG4gIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhyZXNob2xkKClcbiAgICAgICAgLmRvbWFpbihkb21haW4pXG4gICAgICAgIC5yYW5nZShyYW5nZSQkMSk7XG4gIH07XG5cbiAgcmV0dXJuIHNjYWxlO1xufVxuXG52YXIgZHVyYXRpb25TZWNvbmQgPSAxMDAwO1xudmFyIGR1cmF0aW9uTWludXRlID0gZHVyYXRpb25TZWNvbmQgKiA2MDtcbnZhciBkdXJhdGlvbkhvdXIgPSBkdXJhdGlvbk1pbnV0ZSAqIDYwO1xudmFyIGR1cmF0aW9uRGF5ID0gZHVyYXRpb25Ib3VyICogMjQ7XG52YXIgZHVyYXRpb25XZWVrID0gZHVyYXRpb25EYXkgKiA3O1xudmFyIGR1cmF0aW9uTW9udGggPSBkdXJhdGlvbkRheSAqIDMwO1xudmFyIGR1cmF0aW9uWWVhciA9IGR1cmF0aW9uRGF5ICogMzY1O1xuXG5mdW5jdGlvbiBkYXRlKHQpIHtcbiAgcmV0dXJuIG5ldyBEYXRlKHQpO1xufVxuXG5mdW5jdGlvbiBudW1iZXIkMSh0KSB7XG4gIHJldHVybiB0IGluc3RhbmNlb2YgRGF0ZSA/ICt0IDogK25ldyBEYXRlKCt0KTtcbn1cblxuZnVuY3Rpb24gY2FsZW5kYXIoeWVhciwgbW9udGgsIHdlZWssIGRheSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1pbGxpc2Vjb25kLCBmb3JtYXQkJDEpIHtcbiAgdmFyIHNjYWxlID0gY29udGludW91cyhkZWludGVycG9sYXRlTGluZWFyLCBkM0ludGVycG9sYXRlLmludGVycG9sYXRlTnVtYmVyKSxcbiAgICAgIGludmVydCA9IHNjYWxlLmludmVydCxcbiAgICAgIGRvbWFpbiA9IHNjYWxlLmRvbWFpbjtcblxuICB2YXIgZm9ybWF0TWlsbGlzZWNvbmQgPSBmb3JtYXQkJDEoXCIuJUxcIiksXG4gICAgICBmb3JtYXRTZWNvbmQgPSBmb3JtYXQkJDEoXCI6JVNcIiksXG4gICAgICBmb3JtYXRNaW51dGUgPSBmb3JtYXQkJDEoXCIlSTolTVwiKSxcbiAgICAgIGZvcm1hdEhvdXIgPSBmb3JtYXQkJDEoXCIlSSAlcFwiKSxcbiAgICAgIGZvcm1hdERheSA9IGZvcm1hdCQkMShcIiVhICVkXCIpLFxuICAgICAgZm9ybWF0V2VlayA9IGZvcm1hdCQkMShcIiViICVkXCIpLFxuICAgICAgZm9ybWF0TW9udGggPSBmb3JtYXQkJDEoXCIlQlwiKSxcbiAgICAgIGZvcm1hdFllYXIgPSBmb3JtYXQkJDEoXCIlWVwiKTtcblxuICB2YXIgdGlja0ludGVydmFscyA9IFtcbiAgICBbc2Vjb25kLCAgMSwgICAgICBkdXJhdGlvblNlY29uZF0sXG4gICAgW3NlY29uZCwgIDUsICA1ICogZHVyYXRpb25TZWNvbmRdLFxuICAgIFtzZWNvbmQsIDE1LCAxNSAqIGR1cmF0aW9uU2Vjb25kXSxcbiAgICBbc2Vjb25kLCAzMCwgMzAgKiBkdXJhdGlvblNlY29uZF0sXG4gICAgW21pbnV0ZSwgIDEsICAgICAgZHVyYXRpb25NaW51dGVdLFxuICAgIFttaW51dGUsICA1LCAgNSAqIGR1cmF0aW9uTWludXRlXSxcbiAgICBbbWludXRlLCAxNSwgMTUgKiBkdXJhdGlvbk1pbnV0ZV0sXG4gICAgW21pbnV0ZSwgMzAsIDMwICogZHVyYXRpb25NaW51dGVdLFxuICAgIFsgIGhvdXIsICAxLCAgICAgIGR1cmF0aW9uSG91ciAgXSxcbiAgICBbICBob3VyLCAgMywgIDMgKiBkdXJhdGlvbkhvdXIgIF0sXG4gICAgWyAgaG91ciwgIDYsICA2ICogZHVyYXRpb25Ib3VyICBdLFxuICAgIFsgIGhvdXIsIDEyLCAxMiAqIGR1cmF0aW9uSG91ciAgXSxcbiAgICBbICAgZGF5LCAgMSwgICAgICBkdXJhdGlvbkRheSAgIF0sXG4gICAgWyAgIGRheSwgIDIsICAyICogZHVyYXRpb25EYXkgICBdLFxuICAgIFsgIHdlZWssICAxLCAgICAgIGR1cmF0aW9uV2VlayAgXSxcbiAgICBbIG1vbnRoLCAgMSwgICAgICBkdXJhdGlvbk1vbnRoIF0sXG4gICAgWyBtb250aCwgIDMsICAzICogZHVyYXRpb25Nb250aCBdLFxuICAgIFsgIHllYXIsICAxLCAgICAgIGR1cmF0aW9uWWVhciAgXVxuICBdO1xuXG4gIGZ1bmN0aW9uIHRpY2tGb3JtYXQoZGF0ZSkge1xuICAgIHJldHVybiAoc2Vjb25kKGRhdGUpIDwgZGF0ZSA/IGZvcm1hdE1pbGxpc2Vjb25kXG4gICAgICAgIDogbWludXRlKGRhdGUpIDwgZGF0ZSA/IGZvcm1hdFNlY29uZFxuICAgICAgICA6IGhvdXIoZGF0ZSkgPCBkYXRlID8gZm9ybWF0TWludXRlXG4gICAgICAgIDogZGF5KGRhdGUpIDwgZGF0ZSA/IGZvcm1hdEhvdXJcbiAgICAgICAgOiBtb250aChkYXRlKSA8IGRhdGUgPyAod2VlayhkYXRlKSA8IGRhdGUgPyBmb3JtYXREYXkgOiBmb3JtYXRXZWVrKVxuICAgICAgICA6IHllYXIoZGF0ZSkgPCBkYXRlID8gZm9ybWF0TW9udGhcbiAgICAgICAgOiBmb3JtYXRZZWFyKShkYXRlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRpY2tJbnRlcnZhbChpbnRlcnZhbCwgc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgICBpZiAoaW50ZXJ2YWwgPT0gbnVsbCkgaW50ZXJ2YWwgPSAxMDtcblxuICAgIC8vIElmIGEgZGVzaXJlZCB0aWNrIGNvdW50IGlzIHNwZWNpZmllZCwgcGljayBhIHJlYXNvbmFibGUgdGljayBpbnRlcnZhbFxuICAgIC8vIGJhc2VkIG9uIHRoZSBleHRlbnQgb2YgdGhlIGRvbWFpbiBhbmQgYSByb3VnaCBlc3RpbWF0ZSBvZiB0aWNrIHNpemUuXG4gICAgLy8gT3RoZXJ3aXNlLCBhc3N1bWUgaW50ZXJ2YWwgaXMgYWxyZWFkeSBhIHRpbWUgaW50ZXJ2YWwgYW5kIHVzZSBpdC5cbiAgICBpZiAodHlwZW9mIGludGVydmFsID09PSBcIm51bWJlclwiKSB7XG4gICAgICB2YXIgdGFyZ2V0ID0gTWF0aC5hYnMoc3RvcCAtIHN0YXJ0KSAvIGludGVydmFsLFxuICAgICAgICAgIGkgPSBkM0FycmF5LmJpc2VjdG9yKGZ1bmN0aW9uKGkpIHsgcmV0dXJuIGlbMl07IH0pLnJpZ2h0KHRpY2tJbnRlcnZhbHMsIHRhcmdldCk7XG4gICAgICBpZiAoaSA9PT0gdGlja0ludGVydmFscy5sZW5ndGgpIHtcbiAgICAgICAgc3RlcCA9IGQzQXJyYXkudGlja1N0ZXAoc3RhcnQgLyBkdXJhdGlvblllYXIsIHN0b3AgLyBkdXJhdGlvblllYXIsIGludGVydmFsKTtcbiAgICAgICAgaW50ZXJ2YWwgPSB5ZWFyO1xuICAgICAgfSBlbHNlIGlmIChpKSB7XG4gICAgICAgIGkgPSB0aWNrSW50ZXJ2YWxzW3RhcmdldCAvIHRpY2tJbnRlcnZhbHNbaSAtIDFdWzJdIDwgdGlja0ludGVydmFsc1tpXVsyXSAvIHRhcmdldCA/IGkgLSAxIDogaV07XG4gICAgICAgIHN0ZXAgPSBpWzFdO1xuICAgICAgICBpbnRlcnZhbCA9IGlbMF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdGVwID0gTWF0aC5tYXgoZDNBcnJheS50aWNrU3RlcChzdGFydCwgc3RvcCwgaW50ZXJ2YWwpLCAxKTtcbiAgICAgICAgaW50ZXJ2YWwgPSBtaWxsaXNlY29uZDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc3RlcCA9PSBudWxsID8gaW50ZXJ2YWwgOiBpbnRlcnZhbC5ldmVyeShzdGVwKTtcbiAgfVxuXG4gIHNjYWxlLmludmVydCA9IGZ1bmN0aW9uKHkpIHtcbiAgICByZXR1cm4gbmV3IERhdGUoaW52ZXJ0KHkpKTtcbiAgfTtcblxuICBzY2FsZS5kb21haW4gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyBkb21haW4obWFwJDEuY2FsbChfLCBudW1iZXIkMSkpIDogZG9tYWluKCkubWFwKGRhdGUpO1xuICB9O1xuXG4gIHNjYWxlLnRpY2tzID0gZnVuY3Rpb24oaW50ZXJ2YWwsIHN0ZXApIHtcbiAgICB2YXIgZCA9IGRvbWFpbigpLFxuICAgICAgICB0MCA9IGRbMF0sXG4gICAgICAgIHQxID0gZFtkLmxlbmd0aCAtIDFdLFxuICAgICAgICByID0gdDEgPCB0MCxcbiAgICAgICAgdDtcbiAgICBpZiAocikgdCA9IHQwLCB0MCA9IHQxLCB0MSA9IHQ7XG4gICAgdCA9IHRpY2tJbnRlcnZhbChpbnRlcnZhbCwgdDAsIHQxLCBzdGVwKTtcbiAgICB0ID0gdCA/IHQucmFuZ2UodDAsIHQxICsgMSkgOiBbXTsgLy8gaW5jbHVzaXZlIHN0b3BcbiAgICByZXR1cm4gciA/IHQucmV2ZXJzZSgpIDogdDtcbiAgfTtcblxuICBzY2FsZS50aWNrRm9ybWF0ID0gZnVuY3Rpb24oY291bnQsIHNwZWNpZmllcikge1xuICAgIHJldHVybiBzcGVjaWZpZXIgPT0gbnVsbCA/IHRpY2tGb3JtYXQgOiBmb3JtYXQkJDEoc3BlY2lmaWVyKTtcbiAgfTtcblxuICBzY2FsZS5uaWNlID0gZnVuY3Rpb24oaW50ZXJ2YWwsIHN0ZXApIHtcbiAgICB2YXIgZCA9IGRvbWFpbigpO1xuICAgIHJldHVybiAoaW50ZXJ2YWwgPSB0aWNrSW50ZXJ2YWwoaW50ZXJ2YWwsIGRbMF0sIGRbZC5sZW5ndGggLSAxXSwgc3RlcCkpXG4gICAgICAgID8gZG9tYWluKG5pY2UoZCwgaW50ZXJ2YWwpKVxuICAgICAgICA6IHNjYWxlO1xuICB9O1xuXG4gIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gY29weShzY2FsZSwgY2FsZW5kYXIoeWVhciwgbW9udGgsIHdlZWssIGRheSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1pbGxpc2Vjb25kLCBmb3JtYXQkJDEpKTtcbiAgfTtcblxuICByZXR1cm4gc2NhbGU7XG59XG5cbnZhciB0aW1lID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBjYWxlbmRhcihkM1RpbWUudGltZVllYXIsIGQzVGltZS50aW1lTW9udGgsIGQzVGltZS50aW1lV2VlaywgZDNUaW1lLnRpbWVEYXksIGQzVGltZS50aW1lSG91ciwgZDNUaW1lLnRpbWVNaW51dGUsIGQzVGltZS50aW1lU2Vjb25kLCBkM1RpbWUudGltZU1pbGxpc2Vjb25kLCBkM1RpbWVGb3JtYXQudGltZUZvcm1hdCkuZG9tYWluKFtuZXcgRGF0ZSgyMDAwLCAwLCAxKSwgbmV3IERhdGUoMjAwMCwgMCwgMildKTtcbn07XG5cbnZhciB1dGNUaW1lID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBjYWxlbmRhcihkM1RpbWUudXRjWWVhciwgZDNUaW1lLnV0Y01vbnRoLCBkM1RpbWUudXRjV2VlaywgZDNUaW1lLnV0Y0RheSwgZDNUaW1lLnV0Y0hvdXIsIGQzVGltZS51dGNNaW51dGUsIGQzVGltZS51dGNTZWNvbmQsIGQzVGltZS51dGNNaWxsaXNlY29uZCwgZDNUaW1lRm9ybWF0LnV0Y0Zvcm1hdCkuZG9tYWluKFtEYXRlLlVUQygyMDAwLCAwLCAxKSwgRGF0ZS5VVEMoMjAwMCwgMCwgMildKTtcbn07XG5cbnZhciBjb2xvcnMgPSBmdW5jdGlvbihzKSB7XG4gIHJldHVybiBzLm1hdGNoKC8uezZ9L2cpLm1hcChmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIFwiI1wiICsgeDtcbiAgfSk7XG59O1xuXG52YXIgY2F0ZWdvcnkxMCA9IGNvbG9ycyhcIjFmNzdiNGZmN2YwZTJjYTAyY2Q2MjcyODk0NjdiZDhjNTY0YmUzNzdjMjdmN2Y3ZmJjYmQyMjE3YmVjZlwiKTtcblxudmFyIGNhdGVnb3J5MjBiID0gY29sb3JzKFwiMzkzYjc5NTI1NGEzNmI2ZWNmOWM5ZWRlNjM3OTM5OGNhMjUyYjVjZjZiY2VkYjljOGM2ZDMxYmQ5ZTM5ZTdiYTUyZTdjYjk0ODQzYzM5YWQ0OTRhZDY2MTZiZTc5NjljN2I0MTczYTU1MTk0Y2U2ZGJkZGU5ZWQ2XCIpO1xuXG52YXIgY2F0ZWdvcnkyMGMgPSBjb2xvcnMoXCIzMTgyYmQ2YmFlZDY5ZWNhZTFjNmRiZWZlNjU1MGRmZDhkM2NmZGFlNmJmZGQwYTIzMWEzNTQ3NGM0NzZhMWQ5OWJjN2U5YzA3NTZiYjE5ZTlhYzhiY2JkZGNkYWRhZWI2MzYzNjM5Njk2OTZiZGJkYmRkOWQ5ZDlcIik7XG5cbnZhciBjYXRlZ29yeTIwID0gY29sb3JzKFwiMWY3N2I0YWVjN2U4ZmY3ZjBlZmZiYjc4MmNhMDJjOThkZjhhZDYyNzI4ZmY5ODk2OTQ2N2JkYzViMGQ1OGM1NjRiYzQ5Yzk0ZTM3N2MyZjdiNmQyN2Y3ZjdmYzdjN2M3YmNiZDIyZGJkYjhkMTdiZWNmOWVkYWU1XCIpO1xuXG52YXIgY3ViZWhlbGl4JDEgPSBkM0ludGVycG9sYXRlLmludGVycG9sYXRlQ3ViZWhlbGl4TG9uZyhkM0NvbG9yLmN1YmVoZWxpeCgzMDAsIDAuNSwgMC4wKSwgZDNDb2xvci5jdWJlaGVsaXgoLTI0MCwgMC41LCAxLjApKTtcblxudmFyIHdhcm0gPSBkM0ludGVycG9sYXRlLmludGVycG9sYXRlQ3ViZWhlbGl4TG9uZyhkM0NvbG9yLmN1YmVoZWxpeCgtMTAwLCAwLjc1LCAwLjM1KSwgZDNDb2xvci5jdWJlaGVsaXgoODAsIDEuNTAsIDAuOCkpO1xuXG52YXIgY29vbCA9IGQzSW50ZXJwb2xhdGUuaW50ZXJwb2xhdGVDdWJlaGVsaXhMb25nKGQzQ29sb3IuY3ViZWhlbGl4KDI2MCwgMC43NSwgMC4zNSksIGQzQ29sb3IuY3ViZWhlbGl4KDgwLCAxLjUwLCAwLjgpKTtcblxudmFyIHJhaW5ib3cgPSBkM0NvbG9yLmN1YmVoZWxpeCgpO1xuXG52YXIgcmFpbmJvdyQxID0gZnVuY3Rpb24odCkge1xuICBpZiAodCA8IDAgfHwgdCA+IDEpIHQgLT0gTWF0aC5mbG9vcih0KTtcbiAgdmFyIHRzID0gTWF0aC5hYnModCAtIDAuNSk7XG4gIHJhaW5ib3cuaCA9IDM2MCAqIHQgLSAxMDA7XG4gIHJhaW5ib3cucyA9IDEuNSAtIDEuNSAqIHRzO1xuICByYWluYm93LmwgPSAwLjggLSAwLjkgKiB0cztcbiAgcmV0dXJuIHJhaW5ib3cgKyBcIlwiO1xufTtcblxuZnVuY3Rpb24gcmFtcChyYW5nZSQkMSkge1xuICB2YXIgbiA9IHJhbmdlJCQxLmxlbmd0aDtcbiAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICByZXR1cm4gcmFuZ2UkJDFbTWF0aC5tYXgoMCwgTWF0aC5taW4obiAtIDEsIE1hdGguZmxvb3IodCAqIG4pKSldO1xuICB9O1xufVxuXG52YXIgdmlyaWRpcyA9IHJhbXAoY29sb3JzKFwiNDQwMTU0NDQwMjU2NDUwNDU3NDUwNTU5NDYwNzVhNDYwODVjNDYwYTVkNDYwYjVlNDcwZDYwNDcwZTYxNDcxMDYzNDcxMTY0NDcxMzY1NDgxNDY3NDgxNjY4NDgxNzY5NDgxODZhNDgxYTZjNDgxYjZkNDgxYzZlNDgxZDZmNDgxZjcwNDgyMDcxNDgyMTczNDgyMzc0NDgyNDc1NDgyNTc2NDgyNjc3NDgyODc4NDgyOTc5NDcyYTdhNDcyYzdhNDcyZDdiNDcyZTdjNDcyZjdkNDYzMDdlNDYzMjdlNDYzMzdmNDYzNDgwNDUzNTgxNDUzNzgxNDUzODgyNDQzOTgzNDQzYTgzNDQzYjg0NDMzZDg0NDMzZTg1NDIzZjg1NDI0MDg2NDI0MTg2NDE0Mjg3NDE0NDg3NDA0NTg4NDA0Njg4M2Y0Nzg4M2Y0ODg5M2U0OTg5M2U0YTg5M2U0YzhhM2Q0ZDhhM2Q0ZThhM2M0ZjhhM2M1MDhiM2I1MThiM2I1MjhiM2E1MzhiM2E1NDhjMzk1NThjMzk1NjhjMzg1ODhjMzg1OThjMzc1YThjMzc1YjhkMzY1YzhkMzY1ZDhkMzU1ZThkMzU1ZjhkMzQ2MDhkMzQ2MThkMzM2MjhkMzM2MzhkMzI2NDhlMzI2NThlMzE2NjhlMzE2NzhlMzE2ODhlMzA2OThlMzA2YThlMmY2YjhlMmY2YzhlMmU2ZDhlMmU2ZThlMmU2ZjhlMmQ3MDhlMmQ3MThlMmM3MThlMmM3MjhlMmM3MzhlMmI3NDhlMmI3NThlMmE3NjhlMmE3NzhlMmE3ODhlMjk3OThlMjk3YThlMjk3YjhlMjg3YzhlMjg3ZDhlMjc3ZThlMjc3ZjhlMjc4MDhlMjY4MThlMjY4MjhlMjY4MjhlMjU4MzhlMjU4NDhlMjU4NThlMjQ4NjhlMjQ4NzhlMjM4ODhlMjM4OThlMjM4YThkMjI4YjhkMjI4YzhkMjI4ZDhkMjE4ZThkMjE4ZjhkMjE5MDhkMjE5MThjMjA5MjhjMjA5MjhjMjA5MzhjMWY5NDhjMWY5NThiMWY5NjhiMWY5NzhiMWY5ODhiMWY5OThhMWY5YThhMWU5YjhhMWU5Yzg5MWU5ZDg5MWY5ZTg5MWY5Zjg4MWZhMDg4MWZhMTg4MWZhMTg3MWZhMjg3MjBhMzg2MjBhNDg2MjFhNTg1MjFhNjg1MjJhNzg1MjJhODg0MjNhOTgzMjRhYTgzMjVhYjgyMjVhYzgyMjZhZDgxMjdhZDgxMjhhZTgwMjlhZjdmMmFiMDdmMmNiMTdlMmRiMjdkMmViMzdjMmZiNDdjMzFiNTdiMzJiNjdhMzRiNjc5MzViNzc5MzdiODc4MzhiOTc3M2FiYTc2M2JiYjc1M2RiYzc0M2ZiYzczNDBiZDcyNDJiZTcxNDRiZjcwNDZjMDZmNDhjMTZlNGFjMTZkNGNjMjZjNGVjMzZiNTBjNDZhNTJjNTY5NTRjNTY4NTZjNjY3NThjNzY1NWFjODY0NWNjODYzNWVjOTYyNjBjYTYwNjNjYjVmNjVjYjVlNjdjYzVjNjljZDViNmNjZDVhNmVjZTU4NzBjZjU3NzNkMDU2NzVkMDU0NzdkMTUzN2FkMTUxN2NkMjUwN2ZkMzRlODFkMzRkODRkNDRiODZkNTQ5ODlkNTQ4OGJkNjQ2OGVkNjQ1OTBkNzQzOTNkNzQxOTVkODQwOThkODNlOWJkOTNjOWRkOTNiYTBkYTM5YTJkYTM3YTVkYjM2YThkYjM0YWFkYzMyYWRkYzMwYjBkZDJmYjJkZDJkYjVkZTJiYjhkZTI5YmFkZTI4YmRkZjI2YzBkZjI1YzJkZjIzYzVlMDIxYzhlMDIwY2FlMTFmY2RlMTFkZDBlMTFjZDJlMjFiZDVlMjFhZDhlMjE5ZGFlMzE5ZGRlMzE4ZGZlMzE4ZTJlNDE4ZTVlNDE5ZTdlNDE5ZWFlNTFhZWNlNTFiZWZlNTFjZjFlNTFkZjRlNjFlZjZlNjIwZjhlNjIxZmJlNzIzZmRlNzI1XCIpKTtcblxudmFyIG1hZ21hID0gcmFtcChjb2xvcnMoXCIwMDAwMDQwMTAwMDUwMTAxMDYwMTAxMDgwMjAxMDkwMjAyMGIwMjAyMGQwMzAzMGYwMzAzMTIwNDA0MTQwNTA0MTYwNjA1MTgwNjA1MWEwNzA2MWMwODA3MWUwOTA3MjAwYTA4MjIwYjA5MjQwYzA5MjYwZDBhMjkwZTBiMmIxMDBiMmQxMTBjMmYxMjBkMzExMzBkMzQxNDBlMzYxNTBlMzgxNjBmM2IxODBmM2QxOTEwM2YxYTEwNDIxYzEwNDQxZDExNDcxZTExNDkyMDExNGIyMTExNGUyMjExNTAyNDEyNTMyNTEyNTUyNzEyNTgyOTExNWEyYTExNWMyYzExNWYyZDExNjEyZjExNjMzMTExNjUzMzEwNjczNDEwNjkzNjEwNmIzODEwNmMzOTBmNmUzYjBmNzAzZDBmNzEzZjBmNzI0MDBmNzQ0MjBmNzU0NDBmNzY0NTEwNzc0NzEwNzg0OTEwNzg0YTEwNzk0YzExN2E0ZTExN2I0ZjEyN2I1MTEyN2M1MjEzN2M1NDEzN2Q1NjE0N2Q1NzE1N2U1OTE1N2U1YTE2N2U1YzE2N2Y1ZDE3N2Y1ZjE4N2Y2MDE4ODA2MjE5ODA2NDFhODA2NTFhODA2NzFiODA2ODFjODE2YTFjODE2YjFkODE2ZDFkODE2ZTFlODE3MDFmODE3MjFmODE3MzIwODE3NTIxODE3NjIxODE3ODIyODE3OTIyODI3YjIzODI3YzIzODI3ZTI0ODI4MDI1ODI4MTI1ODE4MzI2ODE4NDI2ODE4NjI3ODE4ODI3ODE4OTI4ODE4YjI5ODE4YzI5ODE4ZTJhODE5MDJhODE5MTJiODE5MzJiODA5NDJjODA5NjJjODA5ODJkODA5OTJkODA5YjJlN2Y5YzJlN2Y5ZTJmN2ZhMDJmN2ZhMTMwN2VhMzMwN2VhNTMxN2VhNjMxN2RhODMyN2RhYTMzN2RhYjMzN2NhZDM0N2NhZTM0N2JiMDM1N2JiMjM1N2JiMzM2N2FiNTM2N2FiNzM3NzliODM3NzliYTM4NzhiYzM5NzhiZDM5NzdiZjNhNzdjMDNhNzZjMjNiNzVjNDNjNzVjNTNjNzRjNzNkNzNjODNlNzNjYTNlNzJjYzNmNzFjZDQwNzFjZjQwNzBkMDQxNmZkMjQyNmZkMzQzNmVkNTQ0NmRkNjQ1NmNkODQ1NmNkOTQ2NmJkYjQ3NmFkYzQ4NjlkZTQ5NjhkZjRhNjhlMDRjNjdlMjRkNjZlMzRlNjVlNDRmNjRlNTUwNjRlNzUyNjNlODUzNjJlOTU0NjJlYTU2NjFlYjU3NjBlYzU4NjBlZDVhNWZlZTViNWVlZjVkNWVmMDVmNWVmMTYwNWRmMjYyNWRmMjY0NWNmMzY1NWNmNDY3NWNmNDY5NWNmNTZiNWNmNjZjNWNmNjZlNWNmNzcwNWNmNzcyNWNmODc0NWNmODc2NWNmOTc4NWRmOTc5NWRmOTdiNWRmYTdkNWVmYTdmNWVmYTgxNWZmYjgzNWZmYjg1NjBmYjg3NjFmYzg5NjFmYzhhNjJmYzhjNjNmYzhlNjRmYzkwNjVmZDkyNjZmZDk0NjdmZDk2NjhmZDk4NjlmZDlhNmFmZDliNmJmZTlkNmNmZTlmNmRmZWExNmVmZWEzNmZmZWE1NzFmZWE3NzJmZWE5NzNmZWFhNzRmZWFjNzZmZWFlNzdmZWIwNzhmZWIyN2FmZWI0N2JmZWI2N2NmZWI3N2VmZWI5N2ZmZWJiODFmZWJkODJmZWJmODRmZWMxODVmZWMyODdmZWM0ODhmZWM2OGFmZWM4OGNmZWNhOGRmZWNjOGZmZWNkOTBmZWNmOTJmZWQxOTRmZWQzOTVmZWQ1OTdmZWQ3OTlmZWQ4OWFmZGRhOWNmZGRjOWVmZGRlYTBmZGUwYTFmZGUyYTNmZGUzYTVmZGU1YTdmZGU3YTlmZGU5YWFmZGViYWNmY2VjYWVmY2VlYjBmY2YwYjJmY2YyYjRmY2Y0YjZmY2Y2YjhmY2Y3YjlmY2Y5YmJmY2ZiYmRmY2ZkYmZcIikpO1xuXG52YXIgaW5mZXJubyA9IHJhbXAoY29sb3JzKFwiMDAwMDA0MDEwMDA1MDEwMTA2MDEwMTA4MDIwMTBhMDIwMjBjMDIwMjBlMDMwMjEwMDQwMzEyMDQwMzE0MDUwNDE3MDYwNDE5MDcwNTFiMDgwNTFkMDkwNjFmMGEwNzIyMGIwNzI0MGMwODI2MGQwODI5MGUwOTJiMTAwOTJkMTEwYTMwMTIwYTMyMTQwYjM0MTUwYjM3MTYwYjM5MTgwYzNjMTkwYzNlMWIwYzQxMWMwYzQzMWUwYzQ1MWYwYzQ4MjEwYzRhMjMwYzRjMjQwYzRmMjYwYzUxMjgwYjUzMjkwYjU1MmIwYjU3MmQwYjU5MmYwYTViMzEwYTVjMzIwYTVlMzQwYTVmMzYwOTYxMzgwOTYyMzkwOTYzM2IwOTY0M2QwOTY1M2UwOTY2NDAwYTY3NDIwYTY4NDQwYTY4NDUwYTY5NDcwYjZhNDkwYjZhNGEwYzZiNGMwYzZiNGQwZDZjNGYwZDZjNTEwZTZjNTIwZTZkNTQwZjZkNTUwZjZkNTcxMDZlNTkxMDZlNWExMTZlNWMxMjZlNWQxMjZlNWYxMzZlNjExMzZlNjIxNDZlNjQxNTZlNjUxNTZlNjcxNjZlNjkxNjZlNmExNzZlNmMxODZlNmQxODZlNmYxOTZlNzExOTZlNzIxYTZlNzQxYTZlNzUxYjZlNzcxYzZkNzgxYzZkN2ExZDZkN2MxZDZkN2QxZTZkN2YxZTZjODAxZjZjODIyMDZjODQyMDZiODUyMTZiODcyMTZiODgyMjZhOGEyMjZhOGMyMzY5OGQyMzY5OGYyNDY5OTAyNTY4OTIyNTY4OTMyNjY3OTUyNjY3OTcyNzY2OTgyNzY2OWEyODY1OWIyOTY0OWQyOTY0OWYyYTYzYTAyYTYzYTIyYjYyYTMyYzYxYTUyYzYwYTYyZDYwYTgyZTVmYTkyZTVlYWIyZjVlYWQzMDVkYWUzMDVjYjAzMTViYjEzMjVhYjMzMjVhYjQzMzU5YjYzNDU4YjczNTU3YjkzNTU2YmEzNjU1YmMzNzU0YmQzODUzYmYzOTUyYzAzYTUxYzEzYTUwYzMzYjRmYzQzYzRlYzYzZDRkYzczZTRjYzgzZjRiY2E0MDRhY2I0MTQ5Y2M0MjQ4Y2U0MzQ3Y2Y0NDQ2ZDA0NTQ1ZDI0NjQ0ZDM0NzQzZDQ0ODQyZDU0YTQxZDc0YjNmZDg0YzNlZDk0ZDNkZGE0ZTNjZGI1MDNiZGQ1MTNhZGU1MjM4ZGY1MzM3ZTA1NTM2ZTE1NjM1ZTI1NzM0ZTM1OTMzZTQ1YTMxZTU1YzMwZTY1ZDJmZTc1ZTJlZTg2MDJkZTk2MTJiZWE2MzJhZWI2NDI5ZWI2NjI4ZWM2NzI2ZWQ2OTI1ZWU2YTI0ZWY2YzIzZWY2ZTIxZjA2ZjIwZjE3MTFmZjE3MzFkZjI3NDFjZjM3NjFiZjM3ODE5ZjQ3OTE4ZjU3YjE3ZjU3ZDE1ZjY3ZTE0ZjY4MDEzZjc4MjEyZjc4NDEwZjg4NTBmZjg4NzBlZjg4OTBjZjk4YjBiZjk4YzBhZjk4ZTA5ZmE5MDA4ZmE5MjA3ZmE5NDA3ZmI5NjA2ZmI5NzA2ZmI5OTA2ZmI5YjA2ZmI5ZDA3ZmM5ZjA3ZmNhMTA4ZmNhMzA5ZmNhNTBhZmNhNjBjZmNhODBkZmNhYTBmZmNhYzExZmNhZTEyZmNiMDE0ZmNiMjE2ZmNiNDE4ZmJiNjFhZmJiODFkZmJiYTFmZmJiYzIxZmJiZTIzZmFjMDI2ZmFjMjI4ZmFjNDJhZmFjNjJkZjljNzJmZjljOTMyZjljYjM1ZjhjZDM3ZjhjZjNhZjdkMTNkZjdkMzQwZjZkNTQzZjZkNzQ2ZjVkOTQ5ZjVkYjRjZjRkZDRmZjRkZjUzZjRlMTU2ZjNlMzVhZjNlNTVkZjJlNjYxZjJlODY1ZjJlYTY5ZjFlYzZkZjFlZDcxZjFlZjc1ZjFmMTc5ZjJmMjdkZjJmNDgyZjNmNTg2ZjNmNjhhZjRmODhlZjVmOTkyZjZmYTk2ZjhmYjlhZjlmYzlkZmFmZGExZmNmZmE0XCIpKTtcblxudmFyIHBsYXNtYSA9IHJhbXAoY29sb3JzKFwiMGQwODg3MTAwNzg4MTMwNzg5MTYwNzhhMTkwNjhjMWIwNjhkMWQwNjhlMjAwNjhmMjIwNjkwMjQwNjkxMjYwNTkxMjgwNTkyMmEwNTkzMmMwNTk0MmUwNTk1MmYwNTk2MzEwNTk3MzMwNTk3MzUwNDk4MzcwNDk5MzgwNDlhM2EwNDlhM2MwNDliM2UwNDljM2YwNDljNDEwNDlkNDMwMzllNDQwMzllNDYwMzlmNDgwMzlmNDkwM2EwNGIwM2ExNGMwMmExNGUwMmEyNTAwMmEyNTEwMmEzNTMwMmEzNTUwMmE0NTYwMWE0NTgwMWE0NTkwMWE1NWIwMWE1NWMwMWE2NWUwMWE2NjAwMWE2NjEwMGE3NjMwMGE3NjQwMGE3NjYwMGE3NjcwMGE4NjkwMGE4NmEwMGE4NmMwMGE4NmUwMGE4NmYwMGE4NzEwMGE4NzIwMWE4NzQwMWE4NzUwMWE4NzcwMWE4NzgwMWE4N2EwMmE4N2IwMmE4N2QwM2E4N2UwM2E4ODAwNGE4ODEwNGE3ODMwNWE3ODQwNWE3ODYwNmE2ODcwN2E2ODgwOGE2OGEwOWE1OGIwYWE1OGQwYmE1OGUwY2E0OGYwZGE0OTEwZWEzOTIwZmEzOTQxMGEyOTUxMWExOTYxM2ExOTgxNGEwOTkxNTlmOWExNjlmOWMxNzllOWQxODlkOWUxOTlkYTAxYTljYTExYjliYTIxZDlhYTMxZTlhYTUxZjk5YTYyMDk4YTcyMTk3YTgyMjk2YWEyMzk1YWIyNDk0YWMyNjk0YWQyNzkzYWUyODkyYjAyOTkxYjEyYTkwYjIyYjhmYjMyYzhlYjQyZThkYjUyZjhjYjYzMDhiYjczMThhYjgzMjg5YmEzMzg4YmIzNDg4YmMzNTg3YmQzNzg2YmUzODg1YmYzOTg0YzAzYTgzYzEzYjgyYzIzYzgxYzMzZDgwYzQzZTdmYzU0MDdlYzY0MTdkYzc0MjdjYzg0MzdiYzk0NDdhY2E0NTdhY2I0Njc5Y2M0Nzc4Y2M0OTc3Y2Q0YTc2Y2U0Yjc1Y2Y0Yzc0ZDA0ZDczZDE0ZTcyZDI0ZjcxZDM1MTcxZDQ1MjcwZDU1MzZmZDU1NDZlZDY1NTZkZDc1NjZjZDg1NzZiZDk1ODZhZGE1YTZhZGE1YjY5ZGI1YzY4ZGM1ZDY3ZGQ1ZTY2ZGU1ZjY1ZGU2MTY0ZGY2MjYzZTA2MzYzZTE2NDYyZTI2NTYxZTI2NjYwZTM2ODVmZTQ2OTVlZTU2YTVkZTU2YjVkZTY2YzVjZTc2ZTViZTc2ZjVhZTg3MDU5ZTk3MTU4ZTk3MjU3ZWE3NDU3ZWI3NTU2ZWI3NjU1ZWM3NzU0ZWQ3OTUzZWQ3YTUyZWU3YjUxZWY3YzUxZWY3ZTUwZjA3ZjRmZjA4MDRlZjE4MTRkZjE4MzRjZjI4NDRiZjM4NTRiZjM4NzRhZjQ4ODQ5ZjQ4OTQ4ZjU4YjQ3ZjU4YzQ2ZjY4ZDQ1ZjY4ZjQ0Zjc5MDQ0Zjc5MTQzZjc5MzQyZjg5NDQxZjg5NTQwZjk5NzNmZjk5ODNlZjk5YTNlZmE5YjNkZmE5YzNjZmE5ZTNiZmI5ZjNhZmJhMTM5ZmJhMjM4ZmNhMzM4ZmNhNTM3ZmNhNjM2ZmNhODM1ZmNhOTM0ZmRhYjMzZmRhYzMzZmRhZTMyZmRhZjMxZmRiMTMwZmRiMjJmZmRiNDJmZmRiNTJlZmViNzJkZmViODJjZmViYTJjZmViYjJiZmViZDJhZmViZTJhZmVjMDI5ZmRjMjI5ZmRjMzI4ZmRjNTI3ZmRjNjI3ZmRjODI3ZmRjYTI2ZmRjYjI2ZmNjZDI1ZmNjZTI1ZmNkMDI1ZmNkMjI1ZmJkMzI0ZmJkNTI0ZmJkNzI0ZmFkODI0ZmFkYTI0ZjlkYzI0ZjlkZDI1ZjhkZjI1ZjhlMTI1ZjdlMjI1ZjdlNDI1ZjZlNjI2ZjZlODI2ZjVlOTI2ZjVlYjI3ZjRlZDI3ZjNlZTI3ZjNmMDI3ZjJmMjI3ZjFmNDI2ZjFmNTI1ZjBmNzI0ZjBmOTIxXCIpKTtcblxuZnVuY3Rpb24gc2VxdWVudGlhbChpbnRlcnBvbGF0b3IpIHtcbiAgdmFyIHgwID0gMCxcbiAgICAgIHgxID0gMSxcbiAgICAgIGNsYW1wID0gZmFsc2U7XG5cbiAgZnVuY3Rpb24gc2NhbGUoeCkge1xuICAgIHZhciB0ID0gKHggLSB4MCkgLyAoeDEgLSB4MCk7XG4gICAgcmV0dXJuIGludGVycG9sYXRvcihjbGFtcCA/IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIHQpKSA6IHQpO1xuICB9XG5cbiAgc2NhbGUuZG9tYWluID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHgwID0gK19bMF0sIHgxID0gK19bMV0sIHNjYWxlKSA6IFt4MCwgeDFdO1xuICB9O1xuXG4gIHNjYWxlLmNsYW1wID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNsYW1wID0gISFfLCBzY2FsZSkgOiBjbGFtcDtcbiAgfTtcblxuICBzY2FsZS5pbnRlcnBvbGF0b3IgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaW50ZXJwb2xhdG9yID0gXywgc2NhbGUpIDogaW50ZXJwb2xhdG9yO1xuICB9O1xuXG4gIHNjYWxlLmNvcHkgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gc2VxdWVudGlhbChpbnRlcnBvbGF0b3IpLmRvbWFpbihbeDAsIHgxXSkuY2xhbXAoY2xhbXApO1xuICB9O1xuXG4gIHJldHVybiBsaW5lYXJpc2goc2NhbGUpO1xufVxuXG5leHBvcnRzLnNjYWxlQmFuZCA9IGJhbmQ7XG5leHBvcnRzLnNjYWxlUG9pbnQgPSBwb2ludDtcbmV4cG9ydHMuc2NhbGVJZGVudGl0eSA9IGlkZW50aXR5O1xuZXhwb3J0cy5zY2FsZUxpbmVhciA9IGxpbmVhcjtcbmV4cG9ydHMuc2NhbGVMb2cgPSBsb2c7XG5leHBvcnRzLnNjYWxlT3JkaW5hbCA9IG9yZGluYWw7XG5leHBvcnRzLnNjYWxlSW1wbGljaXQgPSBpbXBsaWNpdDtcbmV4cG9ydHMuc2NhbGVQb3cgPSBwb3c7XG5leHBvcnRzLnNjYWxlU3FydCA9IHNxcnQ7XG5leHBvcnRzLnNjYWxlUXVhbnRpbGUgPSBxdWFudGlsZSQxO1xuZXhwb3J0cy5zY2FsZVF1YW50aXplID0gcXVhbnRpemU7XG5leHBvcnRzLnNjYWxlVGhyZXNob2xkID0gdGhyZXNob2xkO1xuZXhwb3J0cy5zY2FsZVRpbWUgPSB0aW1lO1xuZXhwb3J0cy5zY2FsZVV0YyA9IHV0Y1RpbWU7XG5leHBvcnRzLnNjaGVtZUNhdGVnb3J5MTAgPSBjYXRlZ29yeTEwO1xuZXhwb3J0cy5zY2hlbWVDYXRlZ29yeTIwYiA9IGNhdGVnb3J5MjBiO1xuZXhwb3J0cy5zY2hlbWVDYXRlZ29yeTIwYyA9IGNhdGVnb3J5MjBjO1xuZXhwb3J0cy5zY2hlbWVDYXRlZ29yeTIwID0gY2F0ZWdvcnkyMDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVDdWJlaGVsaXhEZWZhdWx0ID0gY3ViZWhlbGl4JDE7XG5leHBvcnRzLmludGVycG9sYXRlUmFpbmJvdyA9IHJhaW5ib3ckMTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVXYXJtID0gd2FybTtcbmV4cG9ydHMuaW50ZXJwb2xhdGVDb29sID0gY29vbDtcbmV4cG9ydHMuaW50ZXJwb2xhdGVWaXJpZGlzID0gdmlyaWRpcztcbmV4cG9ydHMuaW50ZXJwb2xhdGVNYWdtYSA9IG1hZ21hO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZUluZmVybm8gPSBpbmZlcm5vO1xuZXhwb3J0cy5pbnRlcnBvbGF0ZVBsYXNtYSA9IHBsYXNtYTtcbmV4cG9ydHMuc2NhbGVTZXF1ZW50aWFsID0gc2VxdWVudGlhbDtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtc2VsZWN0aW9uLyBWZXJzaW9uIDEuMy4wLiBDb3B5cmlnaHQgMjAxOCBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciB4aHRtbCA9IFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiO1xuXG52YXIgbmFtZXNwYWNlcyA9IHtcbiAgc3ZnOiBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIsXG4gIHhodG1sOiB4aHRtbCxcbiAgeGxpbms6IFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGlua1wiLFxuICB4bWw6IFwiaHR0cDovL3d3dy53My5vcmcvWE1MLzE5OTgvbmFtZXNwYWNlXCIsXG4gIHhtbG5zOiBcImh0dHA6Ly93d3cudzMub3JnLzIwMDAveG1sbnMvXCJcbn07XG5cbmZ1bmN0aW9uIG5hbWVzcGFjZShuYW1lKSB7XG4gIHZhciBwcmVmaXggPSBuYW1lICs9IFwiXCIsIGkgPSBwcmVmaXguaW5kZXhPZihcIjpcIik7XG4gIGlmIChpID49IDAgJiYgKHByZWZpeCA9IG5hbWUuc2xpY2UoMCwgaSkpICE9PSBcInhtbG5zXCIpIG5hbWUgPSBuYW1lLnNsaWNlKGkgKyAxKTtcbiAgcmV0dXJuIG5hbWVzcGFjZXMuaGFzT3duUHJvcGVydHkocHJlZml4KSA/IHtzcGFjZTogbmFtZXNwYWNlc1twcmVmaXhdLCBsb2NhbDogbmFtZX0gOiBuYW1lO1xufVxuXG5mdW5jdGlvbiBjcmVhdG9ySW5oZXJpdChuYW1lKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgZG9jdW1lbnQgPSB0aGlzLm93bmVyRG9jdW1lbnQsXG4gICAgICAgIHVyaSA9IHRoaXMubmFtZXNwYWNlVVJJO1xuICAgIHJldHVybiB1cmkgPT09IHhodG1sICYmIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5uYW1lc3BhY2VVUkkgPT09IHhodG1sXG4gICAgICAgID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChuYW1lKVxuICAgICAgICA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyh1cmksIG5hbWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBjcmVhdG9yRml4ZWQoZnVsbG5hbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLm93bmVyRG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKGZ1bGxuYW1lLnNwYWNlLCBmdWxsbmFtZS5sb2NhbCk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGNyZWF0b3IobmFtZSkge1xuICB2YXIgZnVsbG5hbWUgPSBuYW1lc3BhY2UobmFtZSk7XG4gIHJldHVybiAoZnVsbG5hbWUubG9jYWxcbiAgICAgID8gY3JlYXRvckZpeGVkXG4gICAgICA6IGNyZWF0b3JJbmhlcml0KShmdWxsbmFtZSk7XG59XG5cbmZ1bmN0aW9uIG5vbmUoKSB7fVxuXG5mdW5jdGlvbiBzZWxlY3RvcihzZWxlY3Rvcikge1xuICByZXR1cm4gc2VsZWN0b3IgPT0gbnVsbCA/IG5vbmUgOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5xdWVyeVNlbGVjdG9yKHNlbGVjdG9yKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX3NlbGVjdChzZWxlY3QpIHtcbiAgaWYgKHR5cGVvZiBzZWxlY3QgIT09IFwiZnVuY3Rpb25cIikgc2VsZWN0ID0gc2VsZWN0b3Ioc2VsZWN0KTtcblxuICBmb3IgKHZhciBncm91cHMgPSB0aGlzLl9ncm91cHMsIG0gPSBncm91cHMubGVuZ3RoLCBzdWJncm91cHMgPSBuZXcgQXJyYXkobSksIGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIG4gPSBncm91cC5sZW5ndGgsIHN1Ymdyb3VwID0gc3ViZ3JvdXBzW2pdID0gbmV3IEFycmF5KG4pLCBub2RlLCBzdWJub2RlLCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgaWYgKChub2RlID0gZ3JvdXBbaV0pICYmIChzdWJub2RlID0gc2VsZWN0LmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgZ3JvdXApKSkge1xuICAgICAgICBpZiAoXCJfX2RhdGFfX1wiIGluIG5vZGUpIHN1Ym5vZGUuX19kYXRhX18gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICBzdWJncm91cFtpXSA9IHN1Ym5vZGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ldyBTZWxlY3Rpb24oc3ViZ3JvdXBzLCB0aGlzLl9wYXJlbnRzKTtcbn1cblxuZnVuY3Rpb24gZW1wdHkoKSB7XG4gIHJldHVybiBbXTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0b3JBbGwoc2VsZWN0b3IpIHtcbiAgcmV0dXJuIHNlbGVjdG9yID09IG51bGwgPyBlbXB0eSA6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fc2VsZWN0QWxsKHNlbGVjdCkge1xuICBpZiAodHlwZW9mIHNlbGVjdCAhPT0gXCJmdW5jdGlvblwiKSBzZWxlY3QgPSBzZWxlY3RvckFsbChzZWxlY3QpO1xuXG4gIGZvciAodmFyIGdyb3VwcyA9IHRoaXMuX2dyb3VwcywgbSA9IGdyb3Vwcy5sZW5ndGgsIHN1Ymdyb3VwcyA9IFtdLCBwYXJlbnRzID0gW10sIGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIG4gPSBncm91cC5sZW5ndGgsIG5vZGUsIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgIHN1Ymdyb3Vwcy5wdXNoKHNlbGVjdC5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGdyb3VwKSk7XG4gICAgICAgIHBhcmVudHMucHVzaChub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3IFNlbGVjdGlvbihzdWJncm91cHMsIHBhcmVudHMpO1xufVxuXG52YXIgbWF0Y2hlciA9IGZ1bmN0aW9uKHNlbGVjdG9yKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5tYXRjaGVzKHNlbGVjdG9yKTtcbiAgfTtcbn07XG5cbmlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIGlmICghZWxlbWVudC5tYXRjaGVzKSB7XG4gICAgdmFyIHZlbmRvck1hdGNoZXMgPSBlbGVtZW50LndlYmtpdE1hdGNoZXNTZWxlY3RvclxuICAgICAgICB8fCBlbGVtZW50Lm1zTWF0Y2hlc1NlbGVjdG9yXG4gICAgICAgIHx8IGVsZW1lbnQubW96TWF0Y2hlc1NlbGVjdG9yXG4gICAgICAgIHx8IGVsZW1lbnQub01hdGNoZXNTZWxlY3RvcjtcbiAgICBtYXRjaGVyID0gZnVuY3Rpb24oc2VsZWN0b3IpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgcmV0dXJuIHZlbmRvck1hdGNoZXMuY2FsbCh0aGlzLCBzZWxlY3Rvcik7XG4gICAgICB9O1xuICAgIH07XG4gIH1cbn1cblxudmFyIG1hdGNoZXIkMSA9IG1hdGNoZXI7XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9maWx0ZXIobWF0Y2gpIHtcbiAgaWYgKHR5cGVvZiBtYXRjaCAhPT0gXCJmdW5jdGlvblwiKSBtYXRjaCA9IG1hdGNoZXIkMShtYXRjaCk7XG5cbiAgZm9yICh2YXIgZ3JvdXBzID0gdGhpcy5fZ3JvdXBzLCBtID0gZ3JvdXBzLmxlbmd0aCwgc3ViZ3JvdXBzID0gbmV3IEFycmF5KG0pLCBqID0gMDsgaiA8IG07ICsraikge1xuICAgIGZvciAodmFyIGdyb3VwID0gZ3JvdXBzW2pdLCBuID0gZ3JvdXAubGVuZ3RoLCBzdWJncm91cCA9IHN1Ymdyb3Vwc1tqXSA9IFtdLCBub2RlLCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgaWYgKChub2RlID0gZ3JvdXBbaV0pICYmIG1hdGNoLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgZ3JvdXApKSB7XG4gICAgICAgIHN1Ymdyb3VwLnB1c2gobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ldyBTZWxlY3Rpb24oc3ViZ3JvdXBzLCB0aGlzLl9wYXJlbnRzKTtcbn1cblxuZnVuY3Rpb24gc3BhcnNlKHVwZGF0ZSkge1xuICByZXR1cm4gbmV3IEFycmF5KHVwZGF0ZS5sZW5ndGgpO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fZW50ZXIoKSB7XG4gIHJldHVybiBuZXcgU2VsZWN0aW9uKHRoaXMuX2VudGVyIHx8IHRoaXMuX2dyb3Vwcy5tYXAoc3BhcnNlKSwgdGhpcy5fcGFyZW50cyk7XG59XG5cbmZ1bmN0aW9uIEVudGVyTm9kZShwYXJlbnQsIGRhdHVtKSB7XG4gIHRoaXMub3duZXJEb2N1bWVudCA9IHBhcmVudC5vd25lckRvY3VtZW50O1xuICB0aGlzLm5hbWVzcGFjZVVSSSA9IHBhcmVudC5uYW1lc3BhY2VVUkk7XG4gIHRoaXMuX25leHQgPSBudWxsO1xuICB0aGlzLl9wYXJlbnQgPSBwYXJlbnQ7XG4gIHRoaXMuX19kYXRhX18gPSBkYXR1bTtcbn1cblxuRW50ZXJOb2RlLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IEVudGVyTm9kZSxcbiAgYXBwZW5kQ2hpbGQ6IGZ1bmN0aW9uKGNoaWxkKSB7IHJldHVybiB0aGlzLl9wYXJlbnQuaW5zZXJ0QmVmb3JlKGNoaWxkLCB0aGlzLl9uZXh0KTsgfSxcbiAgaW5zZXJ0QmVmb3JlOiBmdW5jdGlvbihjaGlsZCwgbmV4dCkgeyByZXR1cm4gdGhpcy5fcGFyZW50Lmluc2VydEJlZm9yZShjaGlsZCwgbmV4dCk7IH0sXG4gIHF1ZXJ5U2VsZWN0b3I6IGZ1bmN0aW9uKHNlbGVjdG9yKSB7IHJldHVybiB0aGlzLl9wYXJlbnQucXVlcnlTZWxlY3RvcihzZWxlY3Rvcik7IH0sXG4gIHF1ZXJ5U2VsZWN0b3JBbGw6IGZ1bmN0aW9uKHNlbGVjdG9yKSB7IHJldHVybiB0aGlzLl9wYXJlbnQucXVlcnlTZWxlY3RvckFsbChzZWxlY3Rvcik7IH1cbn07XG5cbmZ1bmN0aW9uIGNvbnN0YW50KHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufVxuXG52YXIga2V5UHJlZml4ID0gXCIkXCI7IC8vIFByb3RlY3QgYWdhaW5zdCBrZXlzIGxpa2Ug4oCcX19wcm90b19f4oCdLlxuXG5mdW5jdGlvbiBiaW5kSW5kZXgocGFyZW50LCBncm91cCwgZW50ZXIsIHVwZGF0ZSwgZXhpdCwgZGF0YSkge1xuICB2YXIgaSA9IDAsXG4gICAgICBub2RlLFxuICAgICAgZ3JvdXBMZW5ndGggPSBncm91cC5sZW5ndGgsXG4gICAgICBkYXRhTGVuZ3RoID0gZGF0YS5sZW5ndGg7XG5cbiAgLy8gUHV0IGFueSBub24tbnVsbCBub2RlcyB0aGF0IGZpdCBpbnRvIHVwZGF0ZS5cbiAgLy8gUHV0IGFueSBudWxsIG5vZGVzIGludG8gZW50ZXIuXG4gIC8vIFB1dCBhbnkgcmVtYWluaW5nIGRhdGEgaW50byBlbnRlci5cbiAgZm9yICg7IGkgPCBkYXRhTGVuZ3RoOyArK2kpIHtcbiAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICBub2RlLl9fZGF0YV9fID0gZGF0YVtpXTtcbiAgICAgIHVwZGF0ZVtpXSA9IG5vZGU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVudGVyW2ldID0gbmV3IEVudGVyTm9kZShwYXJlbnQsIGRhdGFbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFB1dCBhbnkgbm9uLW51bGwgbm9kZXMgdGhhdCBkb27igJl0IGZpdCBpbnRvIGV4aXQuXG4gIGZvciAoOyBpIDwgZ3JvdXBMZW5ndGg7ICsraSkge1xuICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIHtcbiAgICAgIGV4aXRbaV0gPSBub2RlO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBiaW5kS2V5KHBhcmVudCwgZ3JvdXAsIGVudGVyLCB1cGRhdGUsIGV4aXQsIGRhdGEsIGtleSkge1xuICB2YXIgaSxcbiAgICAgIG5vZGUsXG4gICAgICBub2RlQnlLZXlWYWx1ZSA9IHt9LFxuICAgICAgZ3JvdXBMZW5ndGggPSBncm91cC5sZW5ndGgsXG4gICAgICBkYXRhTGVuZ3RoID0gZGF0YS5sZW5ndGgsXG4gICAgICBrZXlWYWx1ZXMgPSBuZXcgQXJyYXkoZ3JvdXBMZW5ndGgpLFxuICAgICAga2V5VmFsdWU7XG5cbiAgLy8gQ29tcHV0ZSB0aGUga2V5IGZvciBlYWNoIG5vZGUuXG4gIC8vIElmIG11bHRpcGxlIG5vZGVzIGhhdmUgdGhlIHNhbWUga2V5LCB0aGUgZHVwbGljYXRlcyBhcmUgYWRkZWQgdG8gZXhpdC5cbiAgZm9yIChpID0gMDsgaSA8IGdyb3VwTGVuZ3RoOyArK2kpIHtcbiAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICBrZXlWYWx1ZXNbaV0gPSBrZXlWYWx1ZSA9IGtleVByZWZpeCArIGtleS5jYWxsKG5vZGUsIG5vZGUuX19kYXRhX18sIGksIGdyb3VwKTtcbiAgICAgIGlmIChrZXlWYWx1ZSBpbiBub2RlQnlLZXlWYWx1ZSkge1xuICAgICAgICBleGl0W2ldID0gbm9kZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5vZGVCeUtleVZhbHVlW2tleVZhbHVlXSA9IG5vZGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gQ29tcHV0ZSB0aGUga2V5IGZvciBlYWNoIGRhdHVtLlxuICAvLyBJZiB0aGVyZSBhIG5vZGUgYXNzb2NpYXRlZCB3aXRoIHRoaXMga2V5LCBqb2luIGFuZCBhZGQgaXQgdG8gdXBkYXRlLlxuICAvLyBJZiB0aGVyZSBpcyBub3QgKG9yIHRoZSBrZXkgaXMgYSBkdXBsaWNhdGUpLCBhZGQgaXQgdG8gZW50ZXIuXG4gIGZvciAoaSA9IDA7IGkgPCBkYXRhTGVuZ3RoOyArK2kpIHtcbiAgICBrZXlWYWx1ZSA9IGtleVByZWZpeCArIGtleS5jYWxsKHBhcmVudCwgZGF0YVtpXSwgaSwgZGF0YSk7XG4gICAgaWYgKG5vZGUgPSBub2RlQnlLZXlWYWx1ZVtrZXlWYWx1ZV0pIHtcbiAgICAgIHVwZGF0ZVtpXSA9IG5vZGU7XG4gICAgICBub2RlLl9fZGF0YV9fID0gZGF0YVtpXTtcbiAgICAgIG5vZGVCeUtleVZhbHVlW2tleVZhbHVlXSA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVudGVyW2ldID0gbmV3IEVudGVyTm9kZShwYXJlbnQsIGRhdGFbaV0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIEFkZCBhbnkgcmVtYWluaW5nIG5vZGVzIHRoYXQgd2VyZSBub3QgYm91bmQgdG8gZGF0YSB0byBleGl0LlxuICBmb3IgKGkgPSAwOyBpIDwgZ3JvdXBMZW5ndGg7ICsraSkge1xuICAgIGlmICgobm9kZSA9IGdyb3VwW2ldKSAmJiAobm9kZUJ5S2V5VmFsdWVba2V5VmFsdWVzW2ldXSA9PT0gbm9kZSkpIHtcbiAgICAgIGV4aXRbaV0gPSBub2RlO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fZGF0YSh2YWx1ZSwga2V5KSB7XG4gIGlmICghdmFsdWUpIHtcbiAgICBkYXRhID0gbmV3IEFycmF5KHRoaXMuc2l6ZSgpKSwgaiA9IC0xO1xuICAgIHRoaXMuZWFjaChmdW5jdGlvbihkKSB7IGRhdGFbKytqXSA9IGQ7IH0pO1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgdmFyIGJpbmQgPSBrZXkgPyBiaW5kS2V5IDogYmluZEluZGV4LFxuICAgICAgcGFyZW50cyA9IHRoaXMuX3BhcmVudHMsXG4gICAgICBncm91cHMgPSB0aGlzLl9ncm91cHM7XG5cbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJmdW5jdGlvblwiKSB2YWx1ZSA9IGNvbnN0YW50KHZhbHVlKTtcblxuICBmb3IgKHZhciBtID0gZ3JvdXBzLmxlbmd0aCwgdXBkYXRlID0gbmV3IEFycmF5KG0pLCBlbnRlciA9IG5ldyBBcnJheShtKSwgZXhpdCA9IG5ldyBBcnJheShtKSwgaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICB2YXIgcGFyZW50ID0gcGFyZW50c1tqXSxcbiAgICAgICAgZ3JvdXAgPSBncm91cHNbal0sXG4gICAgICAgIGdyb3VwTGVuZ3RoID0gZ3JvdXAubGVuZ3RoLFxuICAgICAgICBkYXRhID0gdmFsdWUuY2FsbChwYXJlbnQsIHBhcmVudCAmJiBwYXJlbnQuX19kYXRhX18sIGosIHBhcmVudHMpLFxuICAgICAgICBkYXRhTGVuZ3RoID0gZGF0YS5sZW5ndGgsXG4gICAgICAgIGVudGVyR3JvdXAgPSBlbnRlcltqXSA9IG5ldyBBcnJheShkYXRhTGVuZ3RoKSxcbiAgICAgICAgdXBkYXRlR3JvdXAgPSB1cGRhdGVbal0gPSBuZXcgQXJyYXkoZGF0YUxlbmd0aCksXG4gICAgICAgIGV4aXRHcm91cCA9IGV4aXRbal0gPSBuZXcgQXJyYXkoZ3JvdXBMZW5ndGgpO1xuXG4gICAgYmluZChwYXJlbnQsIGdyb3VwLCBlbnRlckdyb3VwLCB1cGRhdGVHcm91cCwgZXhpdEdyb3VwLCBkYXRhLCBrZXkpO1xuXG4gICAgLy8gTm93IGNvbm5lY3QgdGhlIGVudGVyIG5vZGVzIHRvIHRoZWlyIGZvbGxvd2luZyB1cGRhdGUgbm9kZSwgc3VjaCB0aGF0XG4gICAgLy8gYXBwZW5kQ2hpbGQgY2FuIGluc2VydCB0aGUgbWF0ZXJpYWxpemVkIGVudGVyIG5vZGUgYmVmb3JlIHRoaXMgbm9kZSxcbiAgICAvLyByYXRoZXIgdGhhbiBhdCB0aGUgZW5kIG9mIHRoZSBwYXJlbnQgbm9kZS5cbiAgICBmb3IgKHZhciBpMCA9IDAsIGkxID0gMCwgcHJldmlvdXMsIG5leHQ7IGkwIDwgZGF0YUxlbmd0aDsgKytpMCkge1xuICAgICAgaWYgKHByZXZpb3VzID0gZW50ZXJHcm91cFtpMF0pIHtcbiAgICAgICAgaWYgKGkwID49IGkxKSBpMSA9IGkwICsgMTtcbiAgICAgICAgd2hpbGUgKCEobmV4dCA9IHVwZGF0ZUdyb3VwW2kxXSkgJiYgKytpMSA8IGRhdGFMZW5ndGgpO1xuICAgICAgICBwcmV2aW91cy5fbmV4dCA9IG5leHQgfHwgbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB1cGRhdGUgPSBuZXcgU2VsZWN0aW9uKHVwZGF0ZSwgcGFyZW50cyk7XG4gIHVwZGF0ZS5fZW50ZXIgPSBlbnRlcjtcbiAgdXBkYXRlLl9leGl0ID0gZXhpdDtcbiAgcmV0dXJuIHVwZGF0ZTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX2V4aXQoKSB7XG4gIHJldHVybiBuZXcgU2VsZWN0aW9uKHRoaXMuX2V4aXQgfHwgdGhpcy5fZ3JvdXBzLm1hcChzcGFyc2UpLCB0aGlzLl9wYXJlbnRzKTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX21lcmdlKHNlbGVjdGlvbiQkMSkge1xuXG4gIGZvciAodmFyIGdyb3VwczAgPSB0aGlzLl9ncm91cHMsIGdyb3VwczEgPSBzZWxlY3Rpb24kJDEuX2dyb3VwcywgbTAgPSBncm91cHMwLmxlbmd0aCwgbTEgPSBncm91cHMxLmxlbmd0aCwgbSA9IE1hdGgubWluKG0wLCBtMSksIG1lcmdlcyA9IG5ldyBBcnJheShtMCksIGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgZ3JvdXAwID0gZ3JvdXBzMFtqXSwgZ3JvdXAxID0gZ3JvdXBzMVtqXSwgbiA9IGdyb3VwMC5sZW5ndGgsIG1lcmdlID0gbWVyZ2VzW2pdID0gbmV3IEFycmF5KG4pLCBub2RlLCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgaWYgKG5vZGUgPSBncm91cDBbaV0gfHwgZ3JvdXAxW2ldKSB7XG4gICAgICAgIG1lcmdlW2ldID0gbm9kZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmb3IgKDsgaiA8IG0wOyArK2opIHtcbiAgICBtZXJnZXNbal0gPSBncm91cHMwW2pdO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBTZWxlY3Rpb24obWVyZ2VzLCB0aGlzLl9wYXJlbnRzKTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX29yZGVyKCkge1xuXG4gIGZvciAodmFyIGdyb3VwcyA9IHRoaXMuX2dyb3VwcywgaiA9IC0xLCBtID0gZ3JvdXBzLmxlbmd0aDsgKytqIDwgbTspIHtcbiAgICBmb3IgKHZhciBncm91cCA9IGdyb3Vwc1tqXSwgaSA9IGdyb3VwLmxlbmd0aCAtIDEsIG5leHQgPSBncm91cFtpXSwgbm9kZTsgLS1pID49IDA7KSB7XG4gICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgIGlmIChuZXh0ICYmIG5leHQgIT09IG5vZGUubmV4dFNpYmxpbmcpIG5leHQucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgbmV4dCk7XG4gICAgICAgIG5leHQgPSBub2RlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fc29ydChjb21wYXJlKSB7XG4gIGlmICghY29tcGFyZSkgY29tcGFyZSA9IGFzY2VuZGluZztcblxuICBmdW5jdGlvbiBjb21wYXJlTm9kZShhLCBiKSB7XG4gICAgcmV0dXJuIGEgJiYgYiA/IGNvbXBhcmUoYS5fX2RhdGFfXywgYi5fX2RhdGFfXykgOiAhYSAtICFiO1xuICB9XG5cbiAgZm9yICh2YXIgZ3JvdXBzID0gdGhpcy5fZ3JvdXBzLCBtID0gZ3JvdXBzLmxlbmd0aCwgc29ydGdyb3VwcyA9IG5ldyBBcnJheShtKSwgaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICBmb3IgKHZhciBncm91cCA9IGdyb3Vwc1tqXSwgbiA9IGdyb3VwLmxlbmd0aCwgc29ydGdyb3VwID0gc29ydGdyb3Vwc1tqXSA9IG5ldyBBcnJheShuKSwgbm9kZSwgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIHtcbiAgICAgICAgc29ydGdyb3VwW2ldID0gbm9kZTtcbiAgICAgIH1cbiAgICB9XG4gICAgc29ydGdyb3VwLnNvcnQoY29tcGFyZU5vZGUpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBTZWxlY3Rpb24oc29ydGdyb3VwcywgdGhpcy5fcGFyZW50cykub3JkZXIoKTtcbn1cblxuZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgcmV0dXJuIGEgPCBiID8gLTEgOiBhID4gYiA/IDEgOiBhID49IGIgPyAwIDogTmFOO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fY2FsbCgpIHtcbiAgdmFyIGNhbGxiYWNrID0gYXJndW1lbnRzWzBdO1xuICBhcmd1bWVudHNbMF0gPSB0aGlzO1xuICBjYWxsYmFjay5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICByZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX25vZGVzKCkge1xuICB2YXIgbm9kZXMgPSBuZXcgQXJyYXkodGhpcy5zaXplKCkpLCBpID0gLTE7XG4gIHRoaXMuZWFjaChmdW5jdGlvbigpIHsgbm9kZXNbKytpXSA9IHRoaXM7IH0pO1xuICByZXR1cm4gbm9kZXM7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9ub2RlKCkge1xuXG4gIGZvciAodmFyIGdyb3VwcyA9IHRoaXMuX2dyb3VwcywgaiA9IDAsIG0gPSBncm91cHMubGVuZ3RoOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIGkgPSAwLCBuID0gZ3JvdXAubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICB2YXIgbm9kZSA9IGdyb3VwW2ldO1xuICAgICAgaWYgKG5vZGUpIHJldHVybiBub2RlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fc2l6ZSgpIHtcbiAgdmFyIHNpemUgPSAwO1xuICB0aGlzLmVhY2goZnVuY3Rpb24oKSB7ICsrc2l6ZTsgfSk7XG4gIHJldHVybiBzaXplO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fZW1wdHkoKSB7XG4gIHJldHVybiAhdGhpcy5ub2RlKCk7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9lYWNoKGNhbGxiYWNrKSB7XG5cbiAgZm9yICh2YXIgZ3JvdXBzID0gdGhpcy5fZ3JvdXBzLCBqID0gMCwgbSA9IGdyb3Vwcy5sZW5ndGg7IGogPCBtOyArK2opIHtcbiAgICBmb3IgKHZhciBncm91cCA9IGdyb3Vwc1tqXSwgaSA9IDAsIG4gPSBncm91cC5sZW5ndGgsIG5vZGU7IGkgPCBuOyArK2kpIHtcbiAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIGNhbGxiYWNrLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgZ3JvdXApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBhdHRyUmVtb3ZlKG5hbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBhdHRyUmVtb3ZlTlMoZnVsbG5hbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlTlMoZnVsbG5hbWUuc3BhY2UsIGZ1bGxuYW1lLmxvY2FsKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYXR0ckNvbnN0YW50KG5hbWUsIHZhbHVlKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnNldEF0dHJpYnV0ZShuYW1lLCB2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGF0dHJDb25zdGFudE5TKGZ1bGxuYW1lLCB2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5zZXRBdHRyaWJ1dGVOUyhmdWxsbmFtZS5zcGFjZSwgZnVsbG5hbWUubG9jYWwsIHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYXR0ckZ1bmN0aW9uKG5hbWUsIHZhbHVlKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdiA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgaWYgKHYgPT0gbnVsbCkgdGhpcy5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7XG4gICAgZWxzZSB0aGlzLnNldEF0dHJpYnV0ZShuYW1lLCB2KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYXR0ckZ1bmN0aW9uTlMoZnVsbG5hbWUsIHZhbHVlKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdiA9IHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgaWYgKHYgPT0gbnVsbCkgdGhpcy5yZW1vdmVBdHRyaWJ1dGVOUyhmdWxsbmFtZS5zcGFjZSwgZnVsbG5hbWUubG9jYWwpO1xuICAgIGVsc2UgdGhpcy5zZXRBdHRyaWJ1dGVOUyhmdWxsbmFtZS5zcGFjZSwgZnVsbG5hbWUubG9jYWwsIHYpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fYXR0cihuYW1lLCB2YWx1ZSkge1xuICB2YXIgZnVsbG5hbWUgPSBuYW1lc3BhY2UobmFtZSk7XG5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgdmFyIG5vZGUgPSB0aGlzLm5vZGUoKTtcbiAgICByZXR1cm4gZnVsbG5hbWUubG9jYWxcbiAgICAgICAgPyBub2RlLmdldEF0dHJpYnV0ZU5TKGZ1bGxuYW1lLnNwYWNlLCBmdWxsbmFtZS5sb2NhbClcbiAgICAgICAgOiBub2RlLmdldEF0dHJpYnV0ZShmdWxsbmFtZSk7XG4gIH1cblxuICByZXR1cm4gdGhpcy5lYWNoKCh2YWx1ZSA9PSBudWxsXG4gICAgICA/IChmdWxsbmFtZS5sb2NhbCA/IGF0dHJSZW1vdmVOUyA6IGF0dHJSZW1vdmUpIDogKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICA/IChmdWxsbmFtZS5sb2NhbCA/IGF0dHJGdW5jdGlvbk5TIDogYXR0ckZ1bmN0aW9uKVxuICAgICAgOiAoZnVsbG5hbWUubG9jYWwgPyBhdHRyQ29uc3RhbnROUyA6IGF0dHJDb25zdGFudCkpKShmdWxsbmFtZSwgdmFsdWUpKTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFZpZXcobm9kZSkge1xuICByZXR1cm4gKG5vZGUub3duZXJEb2N1bWVudCAmJiBub2RlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcpIC8vIG5vZGUgaXMgYSBOb2RlXG4gICAgICB8fCAobm9kZS5kb2N1bWVudCAmJiBub2RlKSAvLyBub2RlIGlzIGEgV2luZG93XG4gICAgICB8fCBub2RlLmRlZmF1bHRWaWV3OyAvLyBub2RlIGlzIGEgRG9jdW1lbnRcbn1cblxuZnVuY3Rpb24gc3R5bGVSZW1vdmUobmFtZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5zdHlsZS5yZW1vdmVQcm9wZXJ0eShuYW1lKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gc3R5bGVDb25zdGFudChuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuc3R5bGUuc2V0UHJvcGVydHkobmFtZSwgdmFsdWUsIHByaW9yaXR5KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gc3R5bGVGdW5jdGlvbihuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciB2ID0gdmFsdWUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICBpZiAodiA9PSBudWxsKSB0aGlzLnN0eWxlLnJlbW92ZVByb3BlcnR5KG5hbWUpO1xuICAgIGVsc2UgdGhpcy5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCB2LCBwcmlvcml0eSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9zdHlsZShuYW1lLCB2YWx1ZSwgcHJpb3JpdHkpIHtcbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPiAxXG4gICAgICA/IHRoaXMuZWFjaCgodmFsdWUgPT0gbnVsbFxuICAgICAgICAgICAgPyBzdHlsZVJlbW92ZSA6IHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICAgICA/IHN0eWxlRnVuY3Rpb25cbiAgICAgICAgICAgIDogc3R5bGVDb25zdGFudCkobmFtZSwgdmFsdWUsIHByaW9yaXR5ID09IG51bGwgPyBcIlwiIDogcHJpb3JpdHkpKVxuICAgICAgOiBzdHlsZVZhbHVlKHRoaXMubm9kZSgpLCBuYW1lKTtcbn1cblxuZnVuY3Rpb24gc3R5bGVWYWx1ZShub2RlLCBuYW1lKSB7XG4gIHJldHVybiBub2RlLnN0eWxlLmdldFByb3BlcnR5VmFsdWUobmFtZSlcbiAgICAgIHx8IGRlZmF1bHRWaWV3KG5vZGUpLmdldENvbXB1dGVkU3R5bGUobm9kZSwgbnVsbCkuZ2V0UHJvcGVydHlWYWx1ZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gcHJvcGVydHlSZW1vdmUobmFtZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgZGVsZXRlIHRoaXNbbmFtZV07XG4gIH07XG59XG5cbmZ1bmN0aW9uIHByb3BlcnR5Q29uc3RhbnQobmFtZSwgdmFsdWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHRoaXNbbmFtZV0gPSB2YWx1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcHJvcGVydHlGdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHYgPSB2YWx1ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIGlmICh2ID09IG51bGwpIGRlbGV0ZSB0aGlzW25hbWVdO1xuICAgIGVsc2UgdGhpc1tuYW1lXSA9IHY7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9wcm9wZXJ0eShuYW1lLCB2YWx1ZSkge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDFcbiAgICAgID8gdGhpcy5lYWNoKCh2YWx1ZSA9PSBudWxsXG4gICAgICAgICAgPyBwcm9wZXJ0eVJlbW92ZSA6IHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICAgPyBwcm9wZXJ0eUZ1bmN0aW9uXG4gICAgICAgICAgOiBwcm9wZXJ0eUNvbnN0YW50KShuYW1lLCB2YWx1ZSkpXG4gICAgICA6IHRoaXMubm9kZSgpW25hbWVdO1xufVxuXG5mdW5jdGlvbiBjbGFzc0FycmF5KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnRyaW0oKS5zcGxpdCgvXnxcXHMrLyk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzTGlzdChub2RlKSB7XG4gIHJldHVybiBub2RlLmNsYXNzTGlzdCB8fCBuZXcgQ2xhc3NMaXN0KG5vZGUpO1xufVxuXG5mdW5jdGlvbiBDbGFzc0xpc3Qobm9kZSkge1xuICB0aGlzLl9ub2RlID0gbm9kZTtcbiAgdGhpcy5fbmFtZXMgPSBjbGFzc0FycmF5KG5vZGUuZ2V0QXR0cmlidXRlKFwiY2xhc3NcIikgfHwgXCJcIik7XG59XG5cbkNsYXNzTGlzdC5wcm90b3R5cGUgPSB7XG4gIGFkZDogZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBpID0gdGhpcy5fbmFtZXMuaW5kZXhPZihuYW1lKTtcbiAgICBpZiAoaSA8IDApIHtcbiAgICAgIHRoaXMuX25hbWVzLnB1c2gobmFtZSk7XG4gICAgICB0aGlzLl9ub2RlLnNldEF0dHJpYnV0ZShcImNsYXNzXCIsIHRoaXMuX25hbWVzLmpvaW4oXCIgXCIpKTtcbiAgICB9XG4gIH0sXG4gIHJlbW92ZTogZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBpID0gdGhpcy5fbmFtZXMuaW5kZXhPZihuYW1lKTtcbiAgICBpZiAoaSA+PSAwKSB7XG4gICAgICB0aGlzLl9uYW1lcy5zcGxpY2UoaSwgMSk7XG4gICAgICB0aGlzLl9ub2RlLnNldEF0dHJpYnV0ZShcImNsYXNzXCIsIHRoaXMuX25hbWVzLmpvaW4oXCIgXCIpKTtcbiAgICB9XG4gIH0sXG4gIGNvbnRhaW5zOiBmdW5jdGlvbihuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMuX25hbWVzLmluZGV4T2YobmFtZSkgPj0gMDtcbiAgfVxufTtcblxuZnVuY3Rpb24gY2xhc3NlZEFkZChub2RlLCBuYW1lcykge1xuICB2YXIgbGlzdCA9IGNsYXNzTGlzdChub2RlKSwgaSA9IC0xLCBuID0gbmFtZXMubGVuZ3RoO1xuICB3aGlsZSAoKytpIDwgbikgbGlzdC5hZGQobmFtZXNbaV0pO1xufVxuXG5mdW5jdGlvbiBjbGFzc2VkUmVtb3ZlKG5vZGUsIG5hbWVzKSB7XG4gIHZhciBsaXN0ID0gY2xhc3NMaXN0KG5vZGUpLCBpID0gLTEsIG4gPSBuYW1lcy5sZW5ndGg7XG4gIHdoaWxlICgrK2kgPCBuKSBsaXN0LnJlbW92ZShuYW1lc1tpXSk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzZWRUcnVlKG5hbWVzKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICBjbGFzc2VkQWRkKHRoaXMsIG5hbWVzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gY2xhc3NlZEZhbHNlKG5hbWVzKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICBjbGFzc2VkUmVtb3ZlKHRoaXMsIG5hbWVzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gY2xhc3NlZEZ1bmN0aW9uKG5hbWVzLCB2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgKHZhbHVlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgPyBjbGFzc2VkQWRkIDogY2xhc3NlZFJlbW92ZSkodGhpcywgbmFtZXMpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fY2xhc3NlZChuYW1lLCB2YWx1ZSkge1xuICB2YXIgbmFtZXMgPSBjbGFzc0FycmF5KG5hbWUgKyBcIlwiKTtcblxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICB2YXIgbGlzdCA9IGNsYXNzTGlzdCh0aGlzLm5vZGUoKSksIGkgPSAtMSwgbiA9IG5hbWVzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgaWYgKCFsaXN0LmNvbnRhaW5zKG5hbWVzW2ldKSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcmV0dXJuIHRoaXMuZWFjaCgodHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCJcbiAgICAgID8gY2xhc3NlZEZ1bmN0aW9uIDogdmFsdWVcbiAgICAgID8gY2xhc3NlZFRydWVcbiAgICAgIDogY2xhc3NlZEZhbHNlKShuYW1lcywgdmFsdWUpKTtcbn1cblxuZnVuY3Rpb24gdGV4dFJlbW92ZSgpIHtcbiAgdGhpcy50ZXh0Q29udGVudCA9IFwiXCI7XG59XG5cbmZ1bmN0aW9uIHRleHRDb25zdGFudCh2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiB0ZXh0RnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciB2ID0gdmFsdWUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB0aGlzLnRleHRDb250ZW50ID0gdiA9PSBudWxsID8gXCJcIiA6IHY7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl90ZXh0KHZhbHVlKSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgICA/IHRoaXMuZWFjaCh2YWx1ZSA9PSBudWxsXG4gICAgICAgICAgPyB0ZXh0UmVtb3ZlIDogKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICAgPyB0ZXh0RnVuY3Rpb25cbiAgICAgICAgICA6IHRleHRDb25zdGFudCkodmFsdWUpKVxuICAgICAgOiB0aGlzLm5vZGUoKS50ZXh0Q29udGVudDtcbn1cblxuZnVuY3Rpb24gaHRtbFJlbW92ZSgpIHtcbiAgdGhpcy5pbm5lckhUTUwgPSBcIlwiO1xufVxuXG5mdW5jdGlvbiBodG1sQ29uc3RhbnQodmFsdWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuaW5uZXJIVE1MID0gdmFsdWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGh0bWxGdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHYgPSB2YWx1ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIHRoaXMuaW5uZXJIVE1MID0gdiA9PSBudWxsID8gXCJcIiA6IHY7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9odG1sKHZhbHVlKSB7XG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgICA/IHRoaXMuZWFjaCh2YWx1ZSA9PSBudWxsXG4gICAgICAgICAgPyBodG1sUmVtb3ZlIDogKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICAgPyBodG1sRnVuY3Rpb25cbiAgICAgICAgICA6IGh0bWxDb25zdGFudCkodmFsdWUpKVxuICAgICAgOiB0aGlzLm5vZGUoKS5pbm5lckhUTUw7XG59XG5cbmZ1bmN0aW9uIHJhaXNlKCkge1xuICBpZiAodGhpcy5uZXh0U2libGluZykgdGhpcy5wYXJlbnROb2RlLmFwcGVuZENoaWxkKHRoaXMpO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fcmFpc2UoKSB7XG4gIHJldHVybiB0aGlzLmVhY2gocmFpc2UpO1xufVxuXG5mdW5jdGlvbiBsb3dlcigpIHtcbiAgaWYgKHRoaXMucHJldmlvdXNTaWJsaW5nKSB0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMsIHRoaXMucGFyZW50Tm9kZS5maXJzdENoaWxkKTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX2xvd2VyKCkge1xuICByZXR1cm4gdGhpcy5lYWNoKGxvd2VyKTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX2FwcGVuZChuYW1lKSB7XG4gIHZhciBjcmVhdGUgPSB0eXBlb2YgbmFtZSA9PT0gXCJmdW5jdGlvblwiID8gbmFtZSA6IGNyZWF0b3IobmFtZSk7XG4gIHJldHVybiB0aGlzLnNlbGVjdChmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5hcHBlbmRDaGlsZChjcmVhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb25zdGFudE51bGwoKSB7XG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25faW5zZXJ0KG5hbWUsIGJlZm9yZSkge1xuICB2YXIgY3JlYXRlID0gdHlwZW9mIG5hbWUgPT09IFwiZnVuY3Rpb25cIiA/IG5hbWUgOiBjcmVhdG9yKG5hbWUpLFxuICAgICAgc2VsZWN0ID0gYmVmb3JlID09IG51bGwgPyBjb25zdGFudE51bGwgOiB0eXBlb2YgYmVmb3JlID09PSBcImZ1bmN0aW9uXCIgPyBiZWZvcmUgOiBzZWxlY3RvcihiZWZvcmUpO1xuICByZXR1cm4gdGhpcy5zZWxlY3QoZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuaW5zZXJ0QmVmb3JlKGNyZWF0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCBzZWxlY3QuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCBudWxsKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSgpIHtcbiAgdmFyIHBhcmVudCA9IHRoaXMucGFyZW50Tm9kZTtcbiAgaWYgKHBhcmVudCkgcGFyZW50LnJlbW92ZUNoaWxkKHRoaXMpO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fcmVtb3ZlKCkge1xuICByZXR1cm4gdGhpcy5lYWNoKHJlbW92ZSk7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9jbG9uZVNoYWxsb3coKSB7XG4gIHJldHVybiB0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMuY2xvbmVOb2RlKGZhbHNlKSwgdGhpcy5uZXh0U2libGluZyk7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9jbG9uZURlZXAoKSB7XG4gIHJldHVybiB0aGlzLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKHRoaXMuY2xvbmVOb2RlKHRydWUpLCB0aGlzLm5leHRTaWJsaW5nKTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX2Nsb25lKGRlZXApIHtcbiAgcmV0dXJuIHRoaXMuc2VsZWN0KGRlZXAgPyBzZWxlY3Rpb25fY2xvbmVEZWVwIDogc2VsZWN0aW9uX2Nsb25lU2hhbGxvdyk7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdGlvbl9kYXR1bSh2YWx1ZSkge1xuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aFxuICAgICAgPyB0aGlzLnByb3BlcnR5KFwiX19kYXRhX19cIiwgdmFsdWUpXG4gICAgICA6IHRoaXMubm9kZSgpLl9fZGF0YV9fO1xufVxuXG52YXIgZmlsdGVyRXZlbnRzID0ge307XG5cbmV4cG9ydHMuZXZlbnQgPSBudWxsO1xuXG5pZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gIHZhciBlbGVtZW50JDEgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIGlmICghKFwib25tb3VzZWVudGVyXCIgaW4gZWxlbWVudCQxKSkge1xuICAgIGZpbHRlckV2ZW50cyA9IHttb3VzZWVudGVyOiBcIm1vdXNlb3ZlclwiLCBtb3VzZWxlYXZlOiBcIm1vdXNlb3V0XCJ9O1xuICB9XG59XG5cbmZ1bmN0aW9uIGZpbHRlckNvbnRleHRMaXN0ZW5lcihsaXN0ZW5lciwgaW5kZXgsIGdyb3VwKSB7XG4gIGxpc3RlbmVyID0gY29udGV4dExpc3RlbmVyKGxpc3RlbmVyLCBpbmRleCwgZ3JvdXApO1xuICByZXR1cm4gZnVuY3Rpb24oZXZlbnQpIHtcbiAgICB2YXIgcmVsYXRlZCA9IGV2ZW50LnJlbGF0ZWRUYXJnZXQ7XG4gICAgaWYgKCFyZWxhdGVkIHx8IChyZWxhdGVkICE9PSB0aGlzICYmICEocmVsYXRlZC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbih0aGlzKSAmIDgpKSkge1xuICAgICAgbGlzdGVuZXIuY2FsbCh0aGlzLCBldmVudCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBjb250ZXh0TGlzdGVuZXIobGlzdGVuZXIsIGluZGV4LCBncm91cCkge1xuICByZXR1cm4gZnVuY3Rpb24oZXZlbnQxKSB7XG4gICAgdmFyIGV2ZW50MCA9IGV4cG9ydHMuZXZlbnQ7IC8vIEV2ZW50cyBjYW4gYmUgcmVlbnRyYW50IChlLmcuLCBmb2N1cykuXG4gICAgZXhwb3J0cy5ldmVudCA9IGV2ZW50MTtcbiAgICB0cnkge1xuICAgICAgbGlzdGVuZXIuY2FsbCh0aGlzLCB0aGlzLl9fZGF0YV9fLCBpbmRleCwgZ3JvdXApO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBleHBvcnRzLmV2ZW50ID0gZXZlbnQwO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcGFyc2VUeXBlbmFtZXModHlwZW5hbWVzKSB7XG4gIHJldHVybiB0eXBlbmFtZXMudHJpbSgpLnNwbGl0KC9efFxccysvKS5tYXAoZnVuY3Rpb24odCkge1xuICAgIHZhciBuYW1lID0gXCJcIiwgaSA9IHQuaW5kZXhPZihcIi5cIik7XG4gICAgaWYgKGkgPj0gMCkgbmFtZSA9IHQuc2xpY2UoaSArIDEpLCB0ID0gdC5zbGljZSgwLCBpKTtcbiAgICByZXR1cm4ge3R5cGU6IHQsIG5hbWU6IG5hbWV9O1xuICB9KTtcbn1cblxuZnVuY3Rpb24gb25SZW1vdmUodHlwZW5hbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciBvbiA9IHRoaXMuX19vbjtcbiAgICBpZiAoIW9uKSByZXR1cm47XG4gICAgZm9yICh2YXIgaiA9IDAsIGkgPSAtMSwgbSA9IG9uLmxlbmd0aCwgbzsgaiA8IG07ICsraikge1xuICAgICAgaWYgKG8gPSBvbltqXSwgKCF0eXBlbmFtZS50eXBlIHx8IG8udHlwZSA9PT0gdHlwZW5hbWUudHlwZSkgJiYgby5uYW1lID09PSB0eXBlbmFtZS5uYW1lKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcihvLnR5cGUsIG8ubGlzdGVuZXIsIG8uY2FwdHVyZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvblsrK2ldID0gbztcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCsraSkgb24ubGVuZ3RoID0gaTtcbiAgICBlbHNlIGRlbGV0ZSB0aGlzLl9fb247XG4gIH07XG59XG5cbmZ1bmN0aW9uIG9uQWRkKHR5cGVuYW1lLCB2YWx1ZSwgY2FwdHVyZSkge1xuICB2YXIgd3JhcCA9IGZpbHRlckV2ZW50cy5oYXNPd25Qcm9wZXJ0eSh0eXBlbmFtZS50eXBlKSA/IGZpbHRlckNvbnRleHRMaXN0ZW5lciA6IGNvbnRleHRMaXN0ZW5lcjtcbiAgcmV0dXJuIGZ1bmN0aW9uKGQsIGksIGdyb3VwKSB7XG4gICAgdmFyIG9uID0gdGhpcy5fX29uLCBvLCBsaXN0ZW5lciA9IHdyYXAodmFsdWUsIGksIGdyb3VwKTtcbiAgICBpZiAob24pIGZvciAodmFyIGogPSAwLCBtID0gb24ubGVuZ3RoOyBqIDwgbTsgKytqKSB7XG4gICAgICBpZiAoKG8gPSBvbltqXSkudHlwZSA9PT0gdHlwZW5hbWUudHlwZSAmJiBvLm5hbWUgPT09IHR5cGVuYW1lLm5hbWUpIHtcbiAgICAgICAgdGhpcy5yZW1vdmVFdmVudExpc3RlbmVyKG8udHlwZSwgby5saXN0ZW5lciwgby5jYXB0dXJlKTtcbiAgICAgICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKG8udHlwZSwgby5saXN0ZW5lciA9IGxpc3RlbmVyLCBvLmNhcHR1cmUgPSBjYXB0dXJlKTtcbiAgICAgICAgby52YWx1ZSA9IHZhbHVlO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcih0eXBlbmFtZS50eXBlLCBsaXN0ZW5lciwgY2FwdHVyZSk7XG4gICAgbyA9IHt0eXBlOiB0eXBlbmFtZS50eXBlLCBuYW1lOiB0eXBlbmFtZS5uYW1lLCB2YWx1ZTogdmFsdWUsIGxpc3RlbmVyOiBsaXN0ZW5lciwgY2FwdHVyZTogY2FwdHVyZX07XG4gICAgaWYgKCFvbikgdGhpcy5fX29uID0gW29dO1xuICAgIGVsc2Ugb24ucHVzaChvKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gc2VsZWN0aW9uX29uKHR5cGVuYW1lLCB2YWx1ZSwgY2FwdHVyZSkge1xuICB2YXIgdHlwZW5hbWVzID0gcGFyc2VUeXBlbmFtZXModHlwZW5hbWUgKyBcIlwiKSwgaSwgbiA9IHR5cGVuYW1lcy5sZW5ndGgsIHQ7XG5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyKSB7XG4gICAgdmFyIG9uID0gdGhpcy5ub2RlKCkuX19vbjtcbiAgICBpZiAob24pIGZvciAodmFyIGogPSAwLCBtID0gb24ubGVuZ3RoLCBvOyBqIDwgbTsgKytqKSB7XG4gICAgICBmb3IgKGkgPSAwLCBvID0gb25bal07IGkgPCBuOyArK2kpIHtcbiAgICAgICAgaWYgKCh0ID0gdHlwZW5hbWVzW2ldKS50eXBlID09PSBvLnR5cGUgJiYgdC5uYW1lID09PSBvLm5hbWUpIHtcbiAgICAgICAgICByZXR1cm4gby52YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm47XG4gIH1cblxuICBvbiA9IHZhbHVlID8gb25BZGQgOiBvblJlbW92ZTtcbiAgaWYgKGNhcHR1cmUgPT0gbnVsbCkgY2FwdHVyZSA9IGZhbHNlO1xuICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB0aGlzLmVhY2gob24odHlwZW5hbWVzW2ldLCB2YWx1ZSwgY2FwdHVyZSkpO1xuICByZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gY3VzdG9tRXZlbnQoZXZlbnQxLCBsaXN0ZW5lciwgdGhhdCwgYXJncykge1xuICB2YXIgZXZlbnQwID0gZXhwb3J0cy5ldmVudDtcbiAgZXZlbnQxLnNvdXJjZUV2ZW50ID0gZXhwb3J0cy5ldmVudDtcbiAgZXhwb3J0cy5ldmVudCA9IGV2ZW50MTtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbGlzdGVuZXIuYXBwbHkodGhhdCwgYXJncyk7XG4gIH0gZmluYWxseSB7XG4gICAgZXhwb3J0cy5ldmVudCA9IGV2ZW50MDtcbiAgfVxufVxuXG5mdW5jdGlvbiBkaXNwYXRjaEV2ZW50KG5vZGUsIHR5cGUsIHBhcmFtcykge1xuICB2YXIgd2luZG93ID0gZGVmYXVsdFZpZXcobm9kZSksXG4gICAgICBldmVudCA9IHdpbmRvdy5DdXN0b21FdmVudDtcblxuICBpZiAodHlwZW9mIGV2ZW50ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICBldmVudCA9IG5ldyBldmVudCh0eXBlLCBwYXJhbXMpO1xuICB9IGVsc2Uge1xuICAgIGV2ZW50ID0gd2luZG93LmRvY3VtZW50LmNyZWF0ZUV2ZW50KFwiRXZlbnRcIik7XG4gICAgaWYgKHBhcmFtcykgZXZlbnQuaW5pdEV2ZW50KHR5cGUsIHBhcmFtcy5idWJibGVzLCBwYXJhbXMuY2FuY2VsYWJsZSksIGV2ZW50LmRldGFpbCA9IHBhcmFtcy5kZXRhaWw7XG4gICAgZWxzZSBldmVudC5pbml0RXZlbnQodHlwZSwgZmFsc2UsIGZhbHNlKTtcbiAgfVxuXG4gIG5vZGUuZGlzcGF0Y2hFdmVudChldmVudCk7XG59XG5cbmZ1bmN0aW9uIGRpc3BhdGNoQ29uc3RhbnQodHlwZSwgcGFyYW1zKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gZGlzcGF0Y2hFdmVudCh0aGlzLCB0eXBlLCBwYXJhbXMpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBkaXNwYXRjaEZ1bmN0aW9uKHR5cGUsIHBhcmFtcykge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGRpc3BhdGNoRXZlbnQodGhpcywgdHlwZSwgcGFyYW1zLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb25fZGlzcGF0Y2godHlwZSwgcGFyYW1zKSB7XG4gIHJldHVybiB0aGlzLmVhY2goKHR5cGVvZiBwYXJhbXMgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgPyBkaXNwYXRjaEZ1bmN0aW9uXG4gICAgICA6IGRpc3BhdGNoQ29uc3RhbnQpKHR5cGUsIHBhcmFtcykpO1xufVxuXG52YXIgcm9vdCA9IFtudWxsXTtcblxuZnVuY3Rpb24gU2VsZWN0aW9uKGdyb3VwcywgcGFyZW50cykge1xuICB0aGlzLl9ncm91cHMgPSBncm91cHM7XG4gIHRoaXMuX3BhcmVudHMgPSBwYXJlbnRzO1xufVxuXG5mdW5jdGlvbiBzZWxlY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgU2VsZWN0aW9uKFtbZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50XV0sIHJvb3QpO1xufVxuXG5TZWxlY3Rpb24ucHJvdG90eXBlID0gc2VsZWN0aW9uLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFNlbGVjdGlvbixcbiAgc2VsZWN0OiBzZWxlY3Rpb25fc2VsZWN0LFxuICBzZWxlY3RBbGw6IHNlbGVjdGlvbl9zZWxlY3RBbGwsXG4gIGZpbHRlcjogc2VsZWN0aW9uX2ZpbHRlcixcbiAgZGF0YTogc2VsZWN0aW9uX2RhdGEsXG4gIGVudGVyOiBzZWxlY3Rpb25fZW50ZXIsXG4gIGV4aXQ6IHNlbGVjdGlvbl9leGl0LFxuICBtZXJnZTogc2VsZWN0aW9uX21lcmdlLFxuICBvcmRlcjogc2VsZWN0aW9uX29yZGVyLFxuICBzb3J0OiBzZWxlY3Rpb25fc29ydCxcbiAgY2FsbDogc2VsZWN0aW9uX2NhbGwsXG4gIG5vZGVzOiBzZWxlY3Rpb25fbm9kZXMsXG4gIG5vZGU6IHNlbGVjdGlvbl9ub2RlLFxuICBzaXplOiBzZWxlY3Rpb25fc2l6ZSxcbiAgZW1wdHk6IHNlbGVjdGlvbl9lbXB0eSxcbiAgZWFjaDogc2VsZWN0aW9uX2VhY2gsXG4gIGF0dHI6IHNlbGVjdGlvbl9hdHRyLFxuICBzdHlsZTogc2VsZWN0aW9uX3N0eWxlLFxuICBwcm9wZXJ0eTogc2VsZWN0aW9uX3Byb3BlcnR5LFxuICBjbGFzc2VkOiBzZWxlY3Rpb25fY2xhc3NlZCxcbiAgdGV4dDogc2VsZWN0aW9uX3RleHQsXG4gIGh0bWw6IHNlbGVjdGlvbl9odG1sLFxuICByYWlzZTogc2VsZWN0aW9uX3JhaXNlLFxuICBsb3dlcjogc2VsZWN0aW9uX2xvd2VyLFxuICBhcHBlbmQ6IHNlbGVjdGlvbl9hcHBlbmQsXG4gIGluc2VydDogc2VsZWN0aW9uX2luc2VydCxcbiAgcmVtb3ZlOiBzZWxlY3Rpb25fcmVtb3ZlLFxuICBjbG9uZTogc2VsZWN0aW9uX2Nsb25lLFxuICBkYXR1bTogc2VsZWN0aW9uX2RhdHVtLFxuICBvbjogc2VsZWN0aW9uX29uLFxuICBkaXNwYXRjaDogc2VsZWN0aW9uX2Rpc3BhdGNoXG59O1xuXG5mdW5jdGlvbiBzZWxlY3Qoc2VsZWN0b3IpIHtcbiAgcmV0dXJuIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIlxuICAgICAgPyBuZXcgU2VsZWN0aW9uKFtbZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzZWxlY3RvcildXSwgW2RvY3VtZW50LmRvY3VtZW50RWxlbWVudF0pXG4gICAgICA6IG5ldyBTZWxlY3Rpb24oW1tzZWxlY3Rvcl1dLCByb290KTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlKG5hbWUpIHtcbiAgcmV0dXJuIHNlbGVjdChjcmVhdG9yKG5hbWUpLmNhbGwoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSk7XG59XG5cbnZhciBuZXh0SWQgPSAwO1xuXG5mdW5jdGlvbiBsb2NhbCgpIHtcbiAgcmV0dXJuIG5ldyBMb2NhbDtcbn1cblxuZnVuY3Rpb24gTG9jYWwoKSB7XG4gIHRoaXMuXyA9IFwiQFwiICsgKCsrbmV4dElkKS50b1N0cmluZygzNik7XG59XG5cbkxvY2FsLnByb3RvdHlwZSA9IGxvY2FsLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IExvY2FsLFxuICBnZXQ6IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICB2YXIgaWQgPSB0aGlzLl87XG4gICAgd2hpbGUgKCEoaWQgaW4gbm9kZSkpIGlmICghKG5vZGUgPSBub2RlLnBhcmVudE5vZGUpKSByZXR1cm47XG4gICAgcmV0dXJuIG5vZGVbaWRdO1xuICB9LFxuICBzZXQ6IGZ1bmN0aW9uKG5vZGUsIHZhbHVlKSB7XG4gICAgcmV0dXJuIG5vZGVbdGhpcy5fXSA9IHZhbHVlO1xuICB9LFxuICByZW1vdmU6IGZ1bmN0aW9uKG5vZGUpIHtcbiAgICByZXR1cm4gdGhpcy5fIGluIG5vZGUgJiYgZGVsZXRlIG5vZGVbdGhpcy5fXTtcbiAgfSxcbiAgdG9TdHJpbmc6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl87XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHNvdXJjZUV2ZW50KCkge1xuICB2YXIgY3VycmVudCA9IGV4cG9ydHMuZXZlbnQsIHNvdXJjZTtcbiAgd2hpbGUgKHNvdXJjZSA9IGN1cnJlbnQuc291cmNlRXZlbnQpIGN1cnJlbnQgPSBzb3VyY2U7XG4gIHJldHVybiBjdXJyZW50O1xufVxuXG5mdW5jdGlvbiBwb2ludChub2RlLCBldmVudCkge1xuICB2YXIgc3ZnID0gbm9kZS5vd25lclNWR0VsZW1lbnQgfHwgbm9kZTtcblxuICBpZiAoc3ZnLmNyZWF0ZVNWR1BvaW50KSB7XG4gICAgdmFyIHBvaW50ID0gc3ZnLmNyZWF0ZVNWR1BvaW50KCk7XG4gICAgcG9pbnQueCA9IGV2ZW50LmNsaWVudFgsIHBvaW50LnkgPSBldmVudC5jbGllbnRZO1xuICAgIHBvaW50ID0gcG9pbnQubWF0cml4VHJhbnNmb3JtKG5vZGUuZ2V0U2NyZWVuQ1RNKCkuaW52ZXJzZSgpKTtcbiAgICByZXR1cm4gW3BvaW50LngsIHBvaW50LnldO1xuICB9XG5cbiAgdmFyIHJlY3QgPSBub2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICByZXR1cm4gW2V2ZW50LmNsaWVudFggLSByZWN0LmxlZnQgLSBub2RlLmNsaWVudExlZnQsIGV2ZW50LmNsaWVudFkgLSByZWN0LnRvcCAtIG5vZGUuY2xpZW50VG9wXTtcbn1cblxuZnVuY3Rpb24gbW91c2Uobm9kZSkge1xuICB2YXIgZXZlbnQgPSBzb3VyY2VFdmVudCgpO1xuICBpZiAoZXZlbnQuY2hhbmdlZFRvdWNoZXMpIGV2ZW50ID0gZXZlbnQuY2hhbmdlZFRvdWNoZXNbMF07XG4gIHJldHVybiBwb2ludChub2RlLCBldmVudCk7XG59XG5cbmZ1bmN0aW9uIHNlbGVjdEFsbChzZWxlY3Rvcikge1xuICByZXR1cm4gdHlwZW9mIHNlbGVjdG9yID09PSBcInN0cmluZ1wiXG4gICAgICA/IG5ldyBTZWxlY3Rpb24oW2RvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoc2VsZWN0b3IpXSwgW2RvY3VtZW50LmRvY3VtZW50RWxlbWVudF0pXG4gICAgICA6IG5ldyBTZWxlY3Rpb24oW3NlbGVjdG9yID09IG51bGwgPyBbXSA6IHNlbGVjdG9yXSwgcm9vdCk7XG59XG5cbmZ1bmN0aW9uIHRvdWNoKG5vZGUsIHRvdWNoZXMsIGlkZW50aWZpZXIpIHtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSBpZGVudGlmaWVyID0gdG91Y2hlcywgdG91Y2hlcyA9IHNvdXJjZUV2ZW50KCkuY2hhbmdlZFRvdWNoZXM7XG5cbiAgZm9yICh2YXIgaSA9IDAsIG4gPSB0b3VjaGVzID8gdG91Y2hlcy5sZW5ndGggOiAwLCB0b3VjaDsgaSA8IG47ICsraSkge1xuICAgIGlmICgodG91Y2ggPSB0b3VjaGVzW2ldKS5pZGVudGlmaWVyID09PSBpZGVudGlmaWVyKSB7XG4gICAgICByZXR1cm4gcG9pbnQobm9kZSwgdG91Y2gpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiB0b3VjaGVzKG5vZGUsIHRvdWNoZXMpIHtcbiAgaWYgKHRvdWNoZXMgPT0gbnVsbCkgdG91Y2hlcyA9IHNvdXJjZUV2ZW50KCkudG91Y2hlcztcblxuICBmb3IgKHZhciBpID0gMCwgbiA9IHRvdWNoZXMgPyB0b3VjaGVzLmxlbmd0aCA6IDAsIHBvaW50cyA9IG5ldyBBcnJheShuKTsgaSA8IG47ICsraSkge1xuICAgIHBvaW50c1tpXSA9IHBvaW50KG5vZGUsIHRvdWNoZXNbaV0pO1xuICB9XG5cbiAgcmV0dXJuIHBvaW50cztcbn1cblxuZXhwb3J0cy5jcmVhdGUgPSBjcmVhdGU7XG5leHBvcnRzLmNyZWF0b3IgPSBjcmVhdG9yO1xuZXhwb3J0cy5sb2NhbCA9IGxvY2FsO1xuZXhwb3J0cy5tYXRjaGVyID0gbWF0Y2hlciQxO1xuZXhwb3J0cy5tb3VzZSA9IG1vdXNlO1xuZXhwb3J0cy5uYW1lc3BhY2UgPSBuYW1lc3BhY2U7XG5leHBvcnRzLm5hbWVzcGFjZXMgPSBuYW1lc3BhY2VzO1xuZXhwb3J0cy5jbGllbnRQb2ludCA9IHBvaW50O1xuZXhwb3J0cy5zZWxlY3QgPSBzZWxlY3Q7XG5leHBvcnRzLnNlbGVjdEFsbCA9IHNlbGVjdEFsbDtcbmV4cG9ydHMuc2VsZWN0aW9uID0gc2VsZWN0aW9uO1xuZXhwb3J0cy5zZWxlY3RvciA9IHNlbGVjdG9yO1xuZXhwb3J0cy5zZWxlY3RvckFsbCA9IHNlbGVjdG9yQWxsO1xuZXhwb3J0cy5zdHlsZSA9IHN0eWxlVmFsdWU7XG5leHBvcnRzLnRvdWNoID0gdG91Y2g7XG5leHBvcnRzLnRvdWNoZXMgPSB0b3VjaGVzO1xuZXhwb3J0cy53aW5kb3cgPSBkZWZhdWx0VmlldztcbmV4cG9ydHMuY3VzdG9tRXZlbnQgPSBjdXN0b21FdmVudDtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtc2hhcGUvIFZlcnNpb24gMS4yLjAuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgcmVxdWlyZSgnZDMtcGF0aCcpKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnLCAnZDMtcGF0aCddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pLGdsb2JhbC5kMykpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMsZDNQYXRoKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGNvbnN0YW50ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4gZnVuY3Rpb24gY29uc3RhbnQoKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59O1xuXG52YXIgYWJzID0gTWF0aC5hYnM7XG52YXIgYXRhbjIgPSBNYXRoLmF0YW4yO1xudmFyIGNvcyA9IE1hdGguY29zO1xudmFyIG1heCA9IE1hdGgubWF4O1xudmFyIG1pbiA9IE1hdGgubWluO1xudmFyIHNpbiA9IE1hdGguc2luO1xudmFyIHNxcnQgPSBNYXRoLnNxcnQ7XG5cbnZhciBlcHNpbG9uID0gMWUtMTI7XG52YXIgcGkgPSBNYXRoLlBJO1xudmFyIGhhbGZQaSA9IHBpIC8gMjtcbnZhciB0YXUgPSAyICogcGk7XG5cbmZ1bmN0aW9uIGFjb3MoeCkge1xuICByZXR1cm4geCA+IDEgPyAwIDogeCA8IC0xID8gcGkgOiBNYXRoLmFjb3MoeCk7XG59XG5cbmZ1bmN0aW9uIGFzaW4oeCkge1xuICByZXR1cm4geCA+PSAxID8gaGFsZlBpIDogeCA8PSAtMSA/IC1oYWxmUGkgOiBNYXRoLmFzaW4oeCk7XG59XG5cbmZ1bmN0aW9uIGFyY0lubmVyUmFkaXVzKGQpIHtcbiAgcmV0dXJuIGQuaW5uZXJSYWRpdXM7XG59XG5cbmZ1bmN0aW9uIGFyY091dGVyUmFkaXVzKGQpIHtcbiAgcmV0dXJuIGQub3V0ZXJSYWRpdXM7XG59XG5cbmZ1bmN0aW9uIGFyY1N0YXJ0QW5nbGUoZCkge1xuICByZXR1cm4gZC5zdGFydEFuZ2xlO1xufVxuXG5mdW5jdGlvbiBhcmNFbmRBbmdsZShkKSB7XG4gIHJldHVybiBkLmVuZEFuZ2xlO1xufVxuXG5mdW5jdGlvbiBhcmNQYWRBbmdsZShkKSB7XG4gIHJldHVybiBkICYmIGQucGFkQW5nbGU7IC8vIE5vdGU6IG9wdGlvbmFsIVxufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3QoeDAsIHkwLCB4MSwgeTEsIHgyLCB5MiwgeDMsIHkzKSB7XG4gIHZhciB4MTAgPSB4MSAtIHgwLCB5MTAgPSB5MSAtIHkwLFxuICAgICAgeDMyID0geDMgLSB4MiwgeTMyID0geTMgLSB5MixcbiAgICAgIHQgPSAoeDMyICogKHkwIC0geTIpIC0geTMyICogKHgwIC0geDIpKSAvICh5MzIgKiB4MTAgLSB4MzIgKiB5MTApO1xuICByZXR1cm4gW3gwICsgdCAqIHgxMCwgeTAgKyB0ICogeTEwXTtcbn1cblxuLy8gQ29tcHV0ZSBwZXJwZW5kaWN1bGFyIG9mZnNldCBsaW5lIG9mIGxlbmd0aCByYy5cbi8vIGh0dHA6Ly9tYXRod29ybGQud29sZnJhbS5jb20vQ2lyY2xlLUxpbmVJbnRlcnNlY3Rpb24uaHRtbFxuZnVuY3Rpb24gY29ybmVyVGFuZ2VudHMoeDAsIHkwLCB4MSwgeTEsIHIxLCByYywgY3cpIHtcbiAgdmFyIHgwMSA9IHgwIC0geDEsXG4gICAgICB5MDEgPSB5MCAtIHkxLFxuICAgICAgbG8gPSAoY3cgPyByYyA6IC1yYykgLyBzcXJ0KHgwMSAqIHgwMSArIHkwMSAqIHkwMSksXG4gICAgICBveCA9IGxvICogeTAxLFxuICAgICAgb3kgPSAtbG8gKiB4MDEsXG4gICAgICB4MTEgPSB4MCArIG94LFxuICAgICAgeTExID0geTAgKyBveSxcbiAgICAgIHgxMCA9IHgxICsgb3gsXG4gICAgICB5MTAgPSB5MSArIG95LFxuICAgICAgeDAwID0gKHgxMSArIHgxMCkgLyAyLFxuICAgICAgeTAwID0gKHkxMSArIHkxMCkgLyAyLFxuICAgICAgZHggPSB4MTAgLSB4MTEsXG4gICAgICBkeSA9IHkxMCAtIHkxMSxcbiAgICAgIGQyID0gZHggKiBkeCArIGR5ICogZHksXG4gICAgICByID0gcjEgLSByYyxcbiAgICAgIEQgPSB4MTEgKiB5MTAgLSB4MTAgKiB5MTEsXG4gICAgICBkID0gKGR5IDwgMCA/IC0xIDogMSkgKiBzcXJ0KG1heCgwLCByICogciAqIGQyIC0gRCAqIEQpKSxcbiAgICAgIGN4MCA9IChEICogZHkgLSBkeCAqIGQpIC8gZDIsXG4gICAgICBjeTAgPSAoLUQgKiBkeCAtIGR5ICogZCkgLyBkMixcbiAgICAgIGN4MSA9IChEICogZHkgKyBkeCAqIGQpIC8gZDIsXG4gICAgICBjeTEgPSAoLUQgKiBkeCArIGR5ICogZCkgLyBkMixcbiAgICAgIGR4MCA9IGN4MCAtIHgwMCxcbiAgICAgIGR5MCA9IGN5MCAtIHkwMCxcbiAgICAgIGR4MSA9IGN4MSAtIHgwMCxcbiAgICAgIGR5MSA9IGN5MSAtIHkwMDtcblxuICAvLyBQaWNrIHRoZSBjbG9zZXIgb2YgdGhlIHR3byBpbnRlcnNlY3Rpb24gcG9pbnRzLlxuICAvLyBUT0RPIElzIHRoZXJlIGEgZmFzdGVyIHdheSB0byBkZXRlcm1pbmUgd2hpY2ggaW50ZXJzZWN0aW9uIHRvIHVzZT9cbiAgaWYgKGR4MCAqIGR4MCArIGR5MCAqIGR5MCA+IGR4MSAqIGR4MSArIGR5MSAqIGR5MSkgY3gwID0gY3gxLCBjeTAgPSBjeTE7XG5cbiAgcmV0dXJuIHtcbiAgICBjeDogY3gwLFxuICAgIGN5OiBjeTAsXG4gICAgeDAxOiAtb3gsXG4gICAgeTAxOiAtb3ksXG4gICAgeDExOiBjeDAgKiAocjEgLyByIC0gMSksXG4gICAgeTExOiBjeTAgKiAocjEgLyByIC0gMSlcbiAgfTtcbn1cblxudmFyIGFyYyA9IGZ1bmN0aW9uKCkge1xuICB2YXIgaW5uZXJSYWRpdXMgPSBhcmNJbm5lclJhZGl1cyxcbiAgICAgIG91dGVyUmFkaXVzID0gYXJjT3V0ZXJSYWRpdXMsXG4gICAgICBjb3JuZXJSYWRpdXMgPSBjb25zdGFudCgwKSxcbiAgICAgIHBhZFJhZGl1cyA9IG51bGwsXG4gICAgICBzdGFydEFuZ2xlID0gYXJjU3RhcnRBbmdsZSxcbiAgICAgIGVuZEFuZ2xlID0gYXJjRW5kQW5nbGUsXG4gICAgICBwYWRBbmdsZSA9IGFyY1BhZEFuZ2xlLFxuICAgICAgY29udGV4dCA9IG51bGw7XG5cbiAgZnVuY3Rpb24gYXJjKCkge1xuICAgIHZhciBidWZmZXIsXG4gICAgICAgIHIsXG4gICAgICAgIHIwID0gK2lubmVyUmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgIHIxID0gK291dGVyUmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgIGEwID0gc3RhcnRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIC0gaGFsZlBpLFxuICAgICAgICBhMSA9IGVuZEFuZ2xlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgLSBoYWxmUGksXG4gICAgICAgIGRhID0gYWJzKGExIC0gYTApLFxuICAgICAgICBjdyA9IGExID4gYTA7XG5cbiAgICBpZiAoIWNvbnRleHQpIGNvbnRleHQgPSBidWZmZXIgPSBkM1BhdGgucGF0aCgpO1xuXG4gICAgLy8gRW5zdXJlIHRoYXQgdGhlIG91dGVyIHJhZGl1cyBpcyBhbHdheXMgbGFyZ2VyIHRoYW4gdGhlIGlubmVyIHJhZGl1cy5cbiAgICBpZiAocjEgPCByMCkgciA9IHIxLCByMSA9IHIwLCByMCA9IHI7XG5cbiAgICAvLyBJcyBpdCBhIHBvaW50P1xuICAgIGlmICghKHIxID4gZXBzaWxvbikpIGNvbnRleHQubW92ZVRvKDAsIDApO1xuXG4gICAgLy8gT3IgaXMgaXQgYSBjaXJjbGUgb3IgYW5udWx1cz9cbiAgICBlbHNlIGlmIChkYSA+IHRhdSAtIGVwc2lsb24pIHtcbiAgICAgIGNvbnRleHQubW92ZVRvKHIxICogY29zKGEwKSwgcjEgKiBzaW4oYTApKTtcbiAgICAgIGNvbnRleHQuYXJjKDAsIDAsIHIxLCBhMCwgYTEsICFjdyk7XG4gICAgICBpZiAocjAgPiBlcHNpbG9uKSB7XG4gICAgICAgIGNvbnRleHQubW92ZVRvKHIwICogY29zKGExKSwgcjAgKiBzaW4oYTEpKTtcbiAgICAgICAgY29udGV4dC5hcmMoMCwgMCwgcjAsIGExLCBhMCwgY3cpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE9yIGlzIGl0IGEgY2lyY3VsYXIgb3IgYW5udWxhciBzZWN0b3I/XG4gICAgZWxzZSB7XG4gICAgICB2YXIgYTAxID0gYTAsXG4gICAgICAgICAgYTExID0gYTEsXG4gICAgICAgICAgYTAwID0gYTAsXG4gICAgICAgICAgYTEwID0gYTEsXG4gICAgICAgICAgZGEwID0gZGEsXG4gICAgICAgICAgZGExID0gZGEsXG4gICAgICAgICAgYXAgPSBwYWRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIC8gMixcbiAgICAgICAgICBycCA9IChhcCA+IGVwc2lsb24pICYmIChwYWRSYWRpdXMgPyArcGFkUmFkaXVzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBzcXJ0KHIwICogcjAgKyByMSAqIHIxKSksXG4gICAgICAgICAgcmMgPSBtaW4oYWJzKHIxIC0gcjApIC8gMiwgK2Nvcm5lclJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSxcbiAgICAgICAgICByYzAgPSByYyxcbiAgICAgICAgICByYzEgPSByYyxcbiAgICAgICAgICB0MCxcbiAgICAgICAgICB0MTtcblxuICAgICAgLy8gQXBwbHkgcGFkZGluZz8gTm90ZSB0aGF0IHNpbmNlIHIxIOKJpSByMCwgZGExIOKJpSBkYTAuXG4gICAgICBpZiAocnAgPiBlcHNpbG9uKSB7XG4gICAgICAgIHZhciBwMCA9IGFzaW4ocnAgLyByMCAqIHNpbihhcCkpLFxuICAgICAgICAgICAgcDEgPSBhc2luKHJwIC8gcjEgKiBzaW4oYXApKTtcbiAgICAgICAgaWYgKChkYTAgLT0gcDAgKiAyKSA+IGVwc2lsb24pIHAwICo9IChjdyA/IDEgOiAtMSksIGEwMCArPSBwMCwgYTEwIC09IHAwO1xuICAgICAgICBlbHNlIGRhMCA9IDAsIGEwMCA9IGExMCA9IChhMCArIGExKSAvIDI7XG4gICAgICAgIGlmICgoZGExIC09IHAxICogMikgPiBlcHNpbG9uKSBwMSAqPSAoY3cgPyAxIDogLTEpLCBhMDEgKz0gcDEsIGExMSAtPSBwMTtcbiAgICAgICAgZWxzZSBkYTEgPSAwLCBhMDEgPSBhMTEgPSAoYTAgKyBhMSkgLyAyO1xuICAgICAgfVxuXG4gICAgICB2YXIgeDAxID0gcjEgKiBjb3MoYTAxKSxcbiAgICAgICAgICB5MDEgPSByMSAqIHNpbihhMDEpLFxuICAgICAgICAgIHgxMCA9IHIwICogY29zKGExMCksXG4gICAgICAgICAgeTEwID0gcjAgKiBzaW4oYTEwKTtcblxuICAgICAgLy8gQXBwbHkgcm91bmRlZCBjb3JuZXJzP1xuICAgICAgaWYgKHJjID4gZXBzaWxvbikge1xuICAgICAgICB2YXIgeDExID0gcjEgKiBjb3MoYTExKSxcbiAgICAgICAgICAgIHkxMSA9IHIxICogc2luKGExMSksXG4gICAgICAgICAgICB4MDAgPSByMCAqIGNvcyhhMDApLFxuICAgICAgICAgICAgeTAwID0gcjAgKiBzaW4oYTAwKTtcblxuICAgICAgICAvLyBSZXN0cmljdCB0aGUgY29ybmVyIHJhZGl1cyBhY2NvcmRpbmcgdG8gdGhlIHNlY3RvciBhbmdsZS5cbiAgICAgICAgaWYgKGRhIDwgcGkpIHtcbiAgICAgICAgICB2YXIgb2MgPSBkYTAgPiBlcHNpbG9uID8gaW50ZXJzZWN0KHgwMSwgeTAxLCB4MDAsIHkwMCwgeDExLCB5MTEsIHgxMCwgeTEwKSA6IFt4MTAsIHkxMF0sXG4gICAgICAgICAgICAgIGF4ID0geDAxIC0gb2NbMF0sXG4gICAgICAgICAgICAgIGF5ID0geTAxIC0gb2NbMV0sXG4gICAgICAgICAgICAgIGJ4ID0geDExIC0gb2NbMF0sXG4gICAgICAgICAgICAgIGJ5ID0geTExIC0gb2NbMV0sXG4gICAgICAgICAgICAgIGtjID0gMSAvIHNpbihhY29zKChheCAqIGJ4ICsgYXkgKiBieSkgLyAoc3FydChheCAqIGF4ICsgYXkgKiBheSkgKiBzcXJ0KGJ4ICogYnggKyBieSAqIGJ5KSkpIC8gMiksXG4gICAgICAgICAgICAgIGxjID0gc3FydChvY1swXSAqIG9jWzBdICsgb2NbMV0gKiBvY1sxXSk7XG4gICAgICAgICAgcmMwID0gbWluKHJjLCAocjAgLSBsYykgLyAoa2MgLSAxKSk7XG4gICAgICAgICAgcmMxID0gbWluKHJjLCAocjEgLSBsYykgLyAoa2MgKyAxKSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gSXMgdGhlIHNlY3RvciBjb2xsYXBzZWQgdG8gYSBsaW5lP1xuICAgICAgaWYgKCEoZGExID4gZXBzaWxvbikpIGNvbnRleHQubW92ZVRvKHgwMSwgeTAxKTtcblxuICAgICAgLy8gRG9lcyB0aGUgc2VjdG9y4oCZcyBvdXRlciByaW5nIGhhdmUgcm91bmRlZCBjb3JuZXJzP1xuICAgICAgZWxzZSBpZiAocmMxID4gZXBzaWxvbikge1xuICAgICAgICB0MCA9IGNvcm5lclRhbmdlbnRzKHgwMCwgeTAwLCB4MDEsIHkwMSwgcjEsIHJjMSwgY3cpO1xuICAgICAgICB0MSA9IGNvcm5lclRhbmdlbnRzKHgxMSwgeTExLCB4MTAsIHkxMCwgcjEsIHJjMSwgY3cpO1xuXG4gICAgICAgIGNvbnRleHQubW92ZVRvKHQwLmN4ICsgdDAueDAxLCB0MC5jeSArIHQwLnkwMSk7XG5cbiAgICAgICAgLy8gSGF2ZSB0aGUgY29ybmVycyBtZXJnZWQ/XG4gICAgICAgIGlmIChyYzEgPCByYykgY29udGV4dC5hcmModDAuY3gsIHQwLmN5LCByYzEsIGF0YW4yKHQwLnkwMSwgdDAueDAxKSwgYXRhbjIodDEueTAxLCB0MS54MDEpLCAhY3cpO1xuXG4gICAgICAgIC8vIE90aGVyd2lzZSwgZHJhdyB0aGUgdHdvIGNvcm5lcnMgYW5kIHRoZSByaW5nLlxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBjb250ZXh0LmFyYyh0MC5jeCwgdDAuY3ksIHJjMSwgYXRhbjIodDAueTAxLCB0MC54MDEpLCBhdGFuMih0MC55MTEsIHQwLngxMSksICFjdyk7XG4gICAgICAgICAgY29udGV4dC5hcmMoMCwgMCwgcjEsIGF0YW4yKHQwLmN5ICsgdDAueTExLCB0MC5jeCArIHQwLngxMSksIGF0YW4yKHQxLmN5ICsgdDEueTExLCB0MS5jeCArIHQxLngxMSksICFjdyk7XG4gICAgICAgICAgY29udGV4dC5hcmModDEuY3gsIHQxLmN5LCByYzEsIGF0YW4yKHQxLnkxMSwgdDEueDExKSwgYXRhbjIodDEueTAxLCB0MS54MDEpLCAhY3cpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIE9yIGlzIHRoZSBvdXRlciByaW5nIGp1c3QgYSBjaXJjdWxhciBhcmM/XG4gICAgICBlbHNlIGNvbnRleHQubW92ZVRvKHgwMSwgeTAxKSwgY29udGV4dC5hcmMoMCwgMCwgcjEsIGEwMSwgYTExLCAhY3cpO1xuXG4gICAgICAvLyBJcyB0aGVyZSBubyBpbm5lciByaW5nLCBhbmQgaXTigJlzIGEgY2lyY3VsYXIgc2VjdG9yP1xuICAgICAgLy8gT3IgcGVyaGFwcyBpdOKAmXMgYW4gYW5udWxhciBzZWN0b3IgY29sbGFwc2VkIGR1ZSB0byBwYWRkaW5nP1xuICAgICAgaWYgKCEocjAgPiBlcHNpbG9uKSB8fCAhKGRhMCA+IGVwc2lsb24pKSBjb250ZXh0LmxpbmVUbyh4MTAsIHkxMCk7XG5cbiAgICAgIC8vIERvZXMgdGhlIHNlY3RvcuKAmXMgaW5uZXIgcmluZyAob3IgcG9pbnQpIGhhdmUgcm91bmRlZCBjb3JuZXJzP1xuICAgICAgZWxzZSBpZiAocmMwID4gZXBzaWxvbikge1xuICAgICAgICB0MCA9IGNvcm5lclRhbmdlbnRzKHgxMCwgeTEwLCB4MTEsIHkxMSwgcjAsIC1yYzAsIGN3KTtcbiAgICAgICAgdDEgPSBjb3JuZXJUYW5nZW50cyh4MDEsIHkwMSwgeDAwLCB5MDAsIHIwLCAtcmMwLCBjdyk7XG5cbiAgICAgICAgY29udGV4dC5saW5lVG8odDAuY3ggKyB0MC54MDEsIHQwLmN5ICsgdDAueTAxKTtcblxuICAgICAgICAvLyBIYXZlIHRoZSBjb3JuZXJzIG1lcmdlZD9cbiAgICAgICAgaWYgKHJjMCA8IHJjKSBjb250ZXh0LmFyYyh0MC5jeCwgdDAuY3ksIHJjMCwgYXRhbjIodDAueTAxLCB0MC54MDEpLCBhdGFuMih0MS55MDEsIHQxLngwMSksICFjdyk7XG5cbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBkcmF3IHRoZSB0d28gY29ybmVycyBhbmQgdGhlIHJpbmcuXG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGNvbnRleHQuYXJjKHQwLmN4LCB0MC5jeSwgcmMwLCBhdGFuMih0MC55MDEsIHQwLngwMSksIGF0YW4yKHQwLnkxMSwgdDAueDExKSwgIWN3KTtcbiAgICAgICAgICBjb250ZXh0LmFyYygwLCAwLCByMCwgYXRhbjIodDAuY3kgKyB0MC55MTEsIHQwLmN4ICsgdDAueDExKSwgYXRhbjIodDEuY3kgKyB0MS55MTEsIHQxLmN4ICsgdDEueDExKSwgY3cpO1xuICAgICAgICAgIGNvbnRleHQuYXJjKHQxLmN4LCB0MS5jeSwgcmMwLCBhdGFuMih0MS55MTEsIHQxLngxMSksIGF0YW4yKHQxLnkwMSwgdDEueDAxKSwgIWN3KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBPciBpcyB0aGUgaW5uZXIgcmluZyBqdXN0IGEgY2lyY3VsYXIgYXJjP1xuICAgICAgZWxzZSBjb250ZXh0LmFyYygwLCAwLCByMCwgYTEwLCBhMDAsIGN3KTtcbiAgICB9XG5cbiAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuXG4gICAgaWYgKGJ1ZmZlcikgcmV0dXJuIGNvbnRleHQgPSBudWxsLCBidWZmZXIgKyBcIlwiIHx8IG51bGw7XG4gIH1cblxuICBhcmMuY2VudHJvaWQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgciA9ICgraW5uZXJSYWRpdXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICtvdXRlclJhZGl1cy5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSAvIDIsXG4gICAgICAgIGEgPSAoK3N0YXJ0QW5nbGUuYXBwbHkodGhpcywgYXJndW1lbnRzKSArICtlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSAvIDIgLSBwaSAvIDI7XG4gICAgcmV0dXJuIFtjb3MoYSkgKiByLCBzaW4oYSkgKiByXTtcbiAgfTtcblxuICBhcmMuaW5uZXJSYWRpdXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoaW5uZXJSYWRpdXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJjKSA6IGlubmVyUmFkaXVzO1xuICB9O1xuXG4gIGFyYy5vdXRlclJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChvdXRlclJhZGl1cyA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmMpIDogb3V0ZXJSYWRpdXM7XG4gIH07XG5cbiAgYXJjLmNvcm5lclJhZGl1cyA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChjb3JuZXJSYWRpdXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJjKSA6IGNvcm5lclJhZGl1cztcbiAgfTtcblxuICBhcmMucGFkUmFkaXVzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBhZFJhZGl1cyA9IF8gPT0gbnVsbCA/IG51bGwgOiB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJjKSA6IHBhZFJhZGl1cztcbiAgfTtcblxuICBhcmMuc3RhcnRBbmdsZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzdGFydEFuZ2xlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGFyYykgOiBzdGFydEFuZ2xlO1xuICB9O1xuXG4gIGFyYy5lbmRBbmdsZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChlbmRBbmdsZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmMpIDogZW5kQW5nbGU7XG4gIH07XG5cbiAgYXJjLnBhZEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHBhZEFuZ2xlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGFyYykgOiBwYWRBbmdsZTtcbiAgfTtcblxuICBhcmMuY29udGV4dCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICgoY29udGV4dCA9IF8gPT0gbnVsbCA/IG51bGwgOiBfKSwgYXJjKSA6IGNvbnRleHQ7XG4gIH07XG5cbiAgcmV0dXJuIGFyYztcbn07XG5cbmZ1bmN0aW9uIExpbmVhcihjb250ZXh0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xufVxuXG5MaW5lYXIucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgdGhpcy5fcG9pbnQgPT09IDEpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDA6IHRoaXMuX3BvaW50ID0gMTsgdGhpcy5fbGluZSA/IHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8oeCwgeSk7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IC8vIHByb2NlZWRcbiAgICAgIGRlZmF1bHQ6IHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpOyBicmVhaztcbiAgICB9XG4gIH1cbn07XG5cbnZhciBjdXJ2ZUxpbmVhciA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcbiAgcmV0dXJuIG5ldyBMaW5lYXIoY29udGV4dCk7XG59O1xuXG5mdW5jdGlvbiB4KHApIHtcbiAgcmV0dXJuIHBbMF07XG59XG5cbmZ1bmN0aW9uIHkocCkge1xuICByZXR1cm4gcFsxXTtcbn1cblxudmFyIGxpbmUgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHgkJDEgPSB4LFxuICAgICAgeSQkMSA9IHksXG4gICAgICBkZWZpbmVkID0gY29uc3RhbnQodHJ1ZSksXG4gICAgICBjb250ZXh0ID0gbnVsbCxcbiAgICAgIGN1cnZlID0gY3VydmVMaW5lYXIsXG4gICAgICBvdXRwdXQgPSBudWxsO1xuXG4gIGZ1bmN0aW9uIGxpbmUoZGF0YSkge1xuICAgIHZhciBpLFxuICAgICAgICBuID0gZGF0YS5sZW5ndGgsXG4gICAgICAgIGQsXG4gICAgICAgIGRlZmluZWQwID0gZmFsc2UsXG4gICAgICAgIGJ1ZmZlcjtcblxuICAgIGlmIChjb250ZXh0ID09IG51bGwpIG91dHB1dCA9IGN1cnZlKGJ1ZmZlciA9IGQzUGF0aC5wYXRoKCkpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8PSBuOyArK2kpIHtcbiAgICAgIGlmICghKGkgPCBuICYmIGRlZmluZWQoZCA9IGRhdGFbaV0sIGksIGRhdGEpKSA9PT0gZGVmaW5lZDApIHtcbiAgICAgICAgaWYgKGRlZmluZWQwID0gIWRlZmluZWQwKSBvdXRwdXQubGluZVN0YXJ0KCk7XG4gICAgICAgIGVsc2Ugb3V0cHV0LmxpbmVFbmQoKTtcbiAgICAgIH1cbiAgICAgIGlmIChkZWZpbmVkMCkgb3V0cHV0LnBvaW50KCt4JCQxKGQsIGksIGRhdGEpLCAreSQkMShkLCBpLCBkYXRhKSk7XG4gICAgfVxuXG4gICAgaWYgKGJ1ZmZlcikgcmV0dXJuIG91dHB1dCA9IG51bGwsIGJ1ZmZlciArIFwiXCIgfHwgbnVsbDtcbiAgfVxuXG4gIGxpbmUueCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4JCQxID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGxpbmUpIDogeCQkMTtcbiAgfTtcblxuICBsaW5lLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSQkMSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBsaW5lKSA6IHkkJDE7XG4gIH07XG5cbiAgbGluZS5kZWZpbmVkID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRlZmluZWQgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCEhXyksIGxpbmUpIDogZGVmaW5lZDtcbiAgfTtcblxuICBsaW5lLmN1cnZlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGN1cnZlID0gXywgY29udGV4dCAhPSBudWxsICYmIChvdXRwdXQgPSBjdXJ2ZShjb250ZXh0KSksIGxpbmUpIDogY3VydmU7XG4gIH07XG5cbiAgbGluZS5jb250ZXh0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKF8gPT0gbnVsbCA/IGNvbnRleHQgPSBvdXRwdXQgPSBudWxsIDogb3V0cHV0ID0gY3VydmUoY29udGV4dCA9IF8pLCBsaW5lKSA6IGNvbnRleHQ7XG4gIH07XG5cbiAgcmV0dXJuIGxpbmU7XG59O1xuXG52YXIgYXJlYSA9IGZ1bmN0aW9uKCkge1xuICB2YXIgeDAgPSB4LFxuICAgICAgeDEgPSBudWxsLFxuICAgICAgeTAgPSBjb25zdGFudCgwKSxcbiAgICAgIHkxID0geSxcbiAgICAgIGRlZmluZWQgPSBjb25zdGFudCh0cnVlKSxcbiAgICAgIGNvbnRleHQgPSBudWxsLFxuICAgICAgY3VydmUgPSBjdXJ2ZUxpbmVhcixcbiAgICAgIG91dHB1dCA9IG51bGw7XG5cbiAgZnVuY3Rpb24gYXJlYShkYXRhKSB7XG4gICAgdmFyIGksXG4gICAgICAgIGosXG4gICAgICAgIGssXG4gICAgICAgIG4gPSBkYXRhLmxlbmd0aCxcbiAgICAgICAgZCxcbiAgICAgICAgZGVmaW5lZDAgPSBmYWxzZSxcbiAgICAgICAgYnVmZmVyLFxuICAgICAgICB4MHogPSBuZXcgQXJyYXkobiksXG4gICAgICAgIHkweiA9IG5ldyBBcnJheShuKTtcblxuICAgIGlmIChjb250ZXh0ID09IG51bGwpIG91dHB1dCA9IGN1cnZlKGJ1ZmZlciA9IGQzUGF0aC5wYXRoKCkpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8PSBuOyArK2kpIHtcbiAgICAgIGlmICghKGkgPCBuICYmIGRlZmluZWQoZCA9IGRhdGFbaV0sIGksIGRhdGEpKSA9PT0gZGVmaW5lZDApIHtcbiAgICAgICAgaWYgKGRlZmluZWQwID0gIWRlZmluZWQwKSB7XG4gICAgICAgICAgaiA9IGk7XG4gICAgICAgICAgb3V0cHV0LmFyZWFTdGFydCgpO1xuICAgICAgICAgIG91dHB1dC5saW5lU3RhcnQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBvdXRwdXQubGluZUVuZCgpO1xuICAgICAgICAgIG91dHB1dC5saW5lU3RhcnQoKTtcbiAgICAgICAgICBmb3IgKGsgPSBpIC0gMTsgayA+PSBqOyAtLWspIHtcbiAgICAgICAgICAgIG91dHB1dC5wb2ludCh4MHpba10sIHkweltrXSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIG91dHB1dC5saW5lRW5kKCk7XG4gICAgICAgICAgb3V0cHV0LmFyZWFFbmQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGRlZmluZWQwKSB7XG4gICAgICAgIHgweltpXSA9ICt4MChkLCBpLCBkYXRhKSwgeTB6W2ldID0gK3kwKGQsIGksIGRhdGEpO1xuICAgICAgICBvdXRwdXQucG9pbnQoeDEgPyAreDEoZCwgaSwgZGF0YSkgOiB4MHpbaV0sIHkxID8gK3kxKGQsIGksIGRhdGEpIDogeTB6W2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoYnVmZmVyKSByZXR1cm4gb3V0cHV0ID0gbnVsbCwgYnVmZmVyICsgXCJcIiB8fCBudWxsO1xuICB9XG5cbiAgZnVuY3Rpb24gYXJlYWxpbmUoKSB7XG4gICAgcmV0dXJuIGxpbmUoKS5kZWZpbmVkKGRlZmluZWQpLmN1cnZlKGN1cnZlKS5jb250ZXh0KGNvbnRleHQpO1xuICB9XG5cbiAgYXJlYS54ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHgwID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIHgxID0gbnVsbCwgYXJlYSkgOiB4MDtcbiAgfTtcblxuICBhcmVhLngwID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHgwID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGFyZWEpIDogeDA7XG4gIH07XG5cbiAgYXJlYS54MSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4MSA9IF8gPT0gbnVsbCA/IG51bGwgOiB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJlYSkgOiB4MTtcbiAgfTtcblxuICBhcmVhLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeTAgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgeTEgPSBudWxsLCBhcmVhKSA6IHkwO1xuICB9O1xuXG4gIGFyZWEueTAgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeTAgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgYXJlYSkgOiB5MDtcbiAgfTtcblxuICBhcmVhLnkxID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHkxID0gXyA9PSBudWxsID8gbnVsbCA6IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBhcmVhKSA6IHkxO1xuICB9O1xuXG4gIGFyZWEubGluZVgwID1cbiAgYXJlYS5saW5lWTAgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gYXJlYWxpbmUoKS54KHgwKS55KHkwKTtcbiAgfTtcblxuICBhcmVhLmxpbmVZMSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBhcmVhbGluZSgpLngoeDApLnkoeTEpO1xuICB9O1xuXG4gIGFyZWEubGluZVgxID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGFyZWFsaW5lKCkueCh4MSkueSh5MCk7XG4gIH07XG5cbiAgYXJlYS5kZWZpbmVkID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGRlZmluZWQgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCEhXyksIGFyZWEpIDogZGVmaW5lZDtcbiAgfTtcblxuICBhcmVhLmN1cnZlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGN1cnZlID0gXywgY29udGV4dCAhPSBudWxsICYmIChvdXRwdXQgPSBjdXJ2ZShjb250ZXh0KSksIGFyZWEpIDogY3VydmU7XG4gIH07XG5cbiAgYXJlYS5jb250ZXh0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKF8gPT0gbnVsbCA/IGNvbnRleHQgPSBvdXRwdXQgPSBudWxsIDogb3V0cHV0ID0gY3VydmUoY29udGV4dCA9IF8pLCBhcmVhKSA6IGNvbnRleHQ7XG4gIH07XG5cbiAgcmV0dXJuIGFyZWE7XG59O1xuXG52YXIgZGVzY2VuZGluZyA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgcmV0dXJuIGIgPCBhID8gLTEgOiBiID4gYSA/IDEgOiBiID49IGEgPyAwIDogTmFOO1xufTtcblxudmFyIGlkZW50aXR5ID0gZnVuY3Rpb24oZCkge1xuICByZXR1cm4gZDtcbn07XG5cbnZhciBwaWUgPSBmdW5jdGlvbigpIHtcbiAgdmFyIHZhbHVlID0gaWRlbnRpdHksXG4gICAgICBzb3J0VmFsdWVzID0gZGVzY2VuZGluZyxcbiAgICAgIHNvcnQgPSBudWxsLFxuICAgICAgc3RhcnRBbmdsZSA9IGNvbnN0YW50KDApLFxuICAgICAgZW5kQW5nbGUgPSBjb25zdGFudCh0YXUpLFxuICAgICAgcGFkQW5nbGUgPSBjb25zdGFudCgwKTtcblxuICBmdW5jdGlvbiBwaWUoZGF0YSkge1xuICAgIHZhciBpLFxuICAgICAgICBuID0gZGF0YS5sZW5ndGgsXG4gICAgICAgIGosXG4gICAgICAgIGssXG4gICAgICAgIHN1bSA9IDAsXG4gICAgICAgIGluZGV4ID0gbmV3IEFycmF5KG4pLFxuICAgICAgICBhcmNzID0gbmV3IEFycmF5KG4pLFxuICAgICAgICBhMCA9ICtzdGFydEFuZ2xlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgIGRhID0gTWF0aC5taW4odGF1LCBNYXRoLm1heCgtdGF1LCBlbmRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIC0gYTApKSxcbiAgICAgICAgYTEsXG4gICAgICAgIHAgPSBNYXRoLm1pbihNYXRoLmFicyhkYSkgLyBuLCBwYWRBbmdsZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpKSxcbiAgICAgICAgcGEgPSBwICogKGRhIDwgMCA/IC0xIDogMSksXG4gICAgICAgIHY7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoKHYgPSBhcmNzW2luZGV4W2ldID0gaV0gPSArdmFsdWUoZGF0YVtpXSwgaSwgZGF0YSkpID4gMCkge1xuICAgICAgICBzdW0gKz0gdjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBPcHRpb25hbGx5IHNvcnQgdGhlIGFyY3MgYnkgcHJldmlvdXNseS1jb21wdXRlZCB2YWx1ZXMgb3IgYnkgZGF0YS5cbiAgICBpZiAoc29ydFZhbHVlcyAhPSBudWxsKSBpbmRleC5zb3J0KGZ1bmN0aW9uKGksIGopIHsgcmV0dXJuIHNvcnRWYWx1ZXMoYXJjc1tpXSwgYXJjc1tqXSk7IH0pO1xuICAgIGVsc2UgaWYgKHNvcnQgIT0gbnVsbCkgaW5kZXguc29ydChmdW5jdGlvbihpLCBqKSB7IHJldHVybiBzb3J0KGRhdGFbaV0sIGRhdGFbal0pOyB9KTtcblxuICAgIC8vIENvbXB1dGUgdGhlIGFyY3MhIFRoZXkgYXJlIHN0b3JlZCBpbiB0aGUgb3JpZ2luYWwgZGF0YSdzIG9yZGVyLlxuICAgIGZvciAoaSA9IDAsIGsgPSBzdW0gPyAoZGEgLSBuICogcGEpIC8gc3VtIDogMDsgaSA8IG47ICsraSwgYTAgPSBhMSkge1xuICAgICAgaiA9IGluZGV4W2ldLCB2ID0gYXJjc1tqXSwgYTEgPSBhMCArICh2ID4gMCA/IHYgKiBrIDogMCkgKyBwYSwgYXJjc1tqXSA9IHtcbiAgICAgICAgZGF0YTogZGF0YVtqXSxcbiAgICAgICAgaW5kZXg6IGksXG4gICAgICAgIHZhbHVlOiB2LFxuICAgICAgICBzdGFydEFuZ2xlOiBhMCxcbiAgICAgICAgZW5kQW5nbGU6IGExLFxuICAgICAgICBwYWRBbmdsZTogcFxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXJjcztcbiAgfVxuXG4gIHBpZS52YWx1ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh2YWx1ZSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBwaWUpIDogdmFsdWU7XG4gIH07XG5cbiAgcGllLnNvcnRWYWx1ZXMgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoc29ydFZhbHVlcyA9IF8sIHNvcnQgPSBudWxsLCBwaWUpIDogc29ydFZhbHVlcztcbiAgfTtcblxuICBwaWUuc29ydCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzb3J0ID0gXywgc29ydFZhbHVlcyA9IG51bGwsIHBpZSkgOiBzb3J0O1xuICB9O1xuXG4gIHBpZS5zdGFydEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHN0YXJ0QW5nbGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgcGllKSA6IHN0YXJ0QW5nbGU7XG4gIH07XG5cbiAgcGllLmVuZEFuZ2xlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGVuZEFuZ2xlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIHBpZSkgOiBlbmRBbmdsZTtcbiAgfTtcblxuICBwaWUucGFkQW5nbGUgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAocGFkQW5nbGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCtfKSwgcGllKSA6IHBhZEFuZ2xlO1xuICB9O1xuXG4gIHJldHVybiBwaWU7XG59O1xuXG52YXIgY3VydmVSYWRpYWxMaW5lYXIgPSBjdXJ2ZVJhZGlhbChjdXJ2ZUxpbmVhcik7XG5cbmZ1bmN0aW9uIFJhZGlhbChjdXJ2ZSkge1xuICB0aGlzLl9jdXJ2ZSA9IGN1cnZlO1xufVxuXG5SYWRpYWwucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2N1cnZlLmFyZWFTdGFydCgpO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9jdXJ2ZS5hcmVhRW5kKCk7XG4gIH0sXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fY3VydmUubGluZVN0YXJ0KCk7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2N1cnZlLmxpbmVFbmQoKTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKGEsIHIpIHtcbiAgICB0aGlzLl9jdXJ2ZS5wb2ludChyICogTWF0aC5zaW4oYSksIHIgKiAtTWF0aC5jb3MoYSkpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBjdXJ2ZVJhZGlhbChjdXJ2ZSkge1xuXG4gIGZ1bmN0aW9uIHJhZGlhbChjb250ZXh0KSB7XG4gICAgcmV0dXJuIG5ldyBSYWRpYWwoY3VydmUoY29udGV4dCkpO1xuICB9XG5cbiAgcmFkaWFsLl9jdXJ2ZSA9IGN1cnZlO1xuXG4gIHJldHVybiByYWRpYWw7XG59XG5cbmZ1bmN0aW9uIGxpbmVSYWRpYWwobCkge1xuICB2YXIgYyA9IGwuY3VydmU7XG5cbiAgbC5hbmdsZSA9IGwueCwgZGVsZXRlIGwueDtcbiAgbC5yYWRpdXMgPSBsLnksIGRlbGV0ZSBsLnk7XG5cbiAgbC5jdXJ2ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IGMoY3VydmVSYWRpYWwoXykpIDogYygpLl9jdXJ2ZTtcbiAgfTtcblxuICByZXR1cm4gbDtcbn1cblxudmFyIGxpbmVSYWRpYWwkMSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gbGluZVJhZGlhbChsaW5lKCkuY3VydmUoY3VydmVSYWRpYWxMaW5lYXIpKTtcbn07XG5cbnZhciBhcmVhUmFkaWFsID0gZnVuY3Rpb24oKSB7XG4gIHZhciBhID0gYXJlYSgpLmN1cnZlKGN1cnZlUmFkaWFsTGluZWFyKSxcbiAgICAgIGMgPSBhLmN1cnZlLFxuICAgICAgeDAgPSBhLmxpbmVYMCxcbiAgICAgIHgxID0gYS5saW5lWDEsXG4gICAgICB5MCA9IGEubGluZVkwLFxuICAgICAgeTEgPSBhLmxpbmVZMTtcblxuICBhLmFuZ2xlID0gYS54LCBkZWxldGUgYS54O1xuICBhLnN0YXJ0QW5nbGUgPSBhLngwLCBkZWxldGUgYS54MDtcbiAgYS5lbmRBbmdsZSA9IGEueDEsIGRlbGV0ZSBhLngxO1xuICBhLnJhZGl1cyA9IGEueSwgZGVsZXRlIGEueTtcbiAgYS5pbm5lclJhZGl1cyA9IGEueTAsIGRlbGV0ZSBhLnkwO1xuICBhLm91dGVyUmFkaXVzID0gYS55MSwgZGVsZXRlIGEueTE7XG4gIGEubGluZVN0YXJ0QW5nbGUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeDAoKSk7IH0sIGRlbGV0ZSBhLmxpbmVYMDtcbiAgYS5saW5lRW5kQW5nbGUgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeDEoKSk7IH0sIGRlbGV0ZSBhLmxpbmVYMTtcbiAgYS5saW5lSW5uZXJSYWRpdXMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeTAoKSk7IH0sIGRlbGV0ZSBhLmxpbmVZMDtcbiAgYS5saW5lT3V0ZXJSYWRpdXMgPSBmdW5jdGlvbigpIHsgcmV0dXJuIGxpbmVSYWRpYWwoeTEoKSk7IH0sIGRlbGV0ZSBhLmxpbmVZMTtcblxuICBhLmN1cnZlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gYyhjdXJ2ZVJhZGlhbChfKSkgOiBjKCkuX2N1cnZlO1xuICB9O1xuXG4gIHJldHVybiBhO1xufTtcblxudmFyIHBvaW50UmFkaWFsID0gZnVuY3Rpb24oeCwgeSkge1xuICByZXR1cm4gWyh5ID0gK3kpICogTWF0aC5jb3MoeCAtPSBNYXRoLlBJIC8gMiksIHkgKiBNYXRoLnNpbih4KV07XG59O1xuXG52YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbmZ1bmN0aW9uIGxpbmtTb3VyY2UoZCkge1xuICByZXR1cm4gZC5zb3VyY2U7XG59XG5cbmZ1bmN0aW9uIGxpbmtUYXJnZXQoZCkge1xuICByZXR1cm4gZC50YXJnZXQ7XG59XG5cbmZ1bmN0aW9uIGxpbmsoY3VydmUpIHtcbiAgdmFyIHNvdXJjZSA9IGxpbmtTb3VyY2UsXG4gICAgICB0YXJnZXQgPSBsaW5rVGFyZ2V0LFxuICAgICAgeCQkMSA9IHgsXG4gICAgICB5JCQxID0geSxcbiAgICAgIGNvbnRleHQgPSBudWxsO1xuXG4gIGZ1bmN0aW9uIGxpbmsoKSB7XG4gICAgdmFyIGJ1ZmZlciwgYXJndiA9IHNsaWNlLmNhbGwoYXJndW1lbnRzKSwgcyA9IHNvdXJjZS5hcHBseSh0aGlzLCBhcmd2KSwgdCA9IHRhcmdldC5hcHBseSh0aGlzLCBhcmd2KTtcbiAgICBpZiAoIWNvbnRleHQpIGNvbnRleHQgPSBidWZmZXIgPSBkM1BhdGgucGF0aCgpO1xuICAgIGN1cnZlKGNvbnRleHQsICt4JCQxLmFwcGx5KHRoaXMsIChhcmd2WzBdID0gcywgYXJndikpLCAreSQkMS5hcHBseSh0aGlzLCBhcmd2KSwgK3gkJDEuYXBwbHkodGhpcywgKGFyZ3ZbMF0gPSB0LCBhcmd2KSksICt5JCQxLmFwcGx5KHRoaXMsIGFyZ3YpKTtcbiAgICBpZiAoYnVmZmVyKSByZXR1cm4gY29udGV4dCA9IG51bGwsIGJ1ZmZlciArIFwiXCIgfHwgbnVsbDtcbiAgfVxuXG4gIGxpbmsuc291cmNlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNvdXJjZSA9IF8sIGxpbmspIDogc291cmNlO1xuICB9O1xuXG4gIGxpbmsudGFyZ2V0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHRhcmdldCA9IF8sIGxpbmspIDogdGFyZ2V0O1xuICB9O1xuXG4gIGxpbmsueCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4JCQxID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIGxpbmspIDogeCQkMTtcbiAgfTtcblxuICBsaW5rLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSQkMSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCBsaW5rKSA6IHkkJDE7XG4gIH07XG5cbiAgbGluay5jb250ZXh0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKChjb250ZXh0ID0gXyA9PSBudWxsID8gbnVsbCA6IF8pLCBsaW5rKSA6IGNvbnRleHQ7XG4gIH07XG5cbiAgcmV0dXJuIGxpbms7XG59XG5cbmZ1bmN0aW9uIGN1cnZlSG9yaXpvbnRhbChjb250ZXh0LCB4MCwgeTAsIHgxLCB5MSkge1xuICBjb250ZXh0Lm1vdmVUbyh4MCwgeTApO1xuICBjb250ZXh0LmJlemllckN1cnZlVG8oeDAgPSAoeDAgKyB4MSkgLyAyLCB5MCwgeDAsIHkxLCB4MSwgeTEpO1xufVxuXG5mdW5jdGlvbiBjdXJ2ZVZlcnRpY2FsKGNvbnRleHQsIHgwLCB5MCwgeDEsIHkxKSB7XG4gIGNvbnRleHQubW92ZVRvKHgwLCB5MCk7XG4gIGNvbnRleHQuYmV6aWVyQ3VydmVUbyh4MCwgeTAgPSAoeTAgKyB5MSkgLyAyLCB4MSwgeTAsIHgxLCB5MSk7XG59XG5cbmZ1bmN0aW9uIGN1cnZlUmFkaWFsJDEoY29udGV4dCwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgdmFyIHAwID0gcG9pbnRSYWRpYWwoeDAsIHkwKSxcbiAgICAgIHAxID0gcG9pbnRSYWRpYWwoeDAsIHkwID0gKHkwICsgeTEpIC8gMiksXG4gICAgICBwMiA9IHBvaW50UmFkaWFsKHgxLCB5MCksXG4gICAgICBwMyA9IHBvaW50UmFkaWFsKHgxLCB5MSk7XG4gIGNvbnRleHQubW92ZVRvKHAwWzBdLCBwMFsxXSk7XG4gIGNvbnRleHQuYmV6aWVyQ3VydmVUbyhwMVswXSwgcDFbMV0sIHAyWzBdLCBwMlsxXSwgcDNbMF0sIHAzWzFdKTtcbn1cblxuZnVuY3Rpb24gbGlua0hvcml6b250YWwoKSB7XG4gIHJldHVybiBsaW5rKGN1cnZlSG9yaXpvbnRhbCk7XG59XG5cbmZ1bmN0aW9uIGxpbmtWZXJ0aWNhbCgpIHtcbiAgcmV0dXJuIGxpbmsoY3VydmVWZXJ0aWNhbCk7XG59XG5cbmZ1bmN0aW9uIGxpbmtSYWRpYWwoKSB7XG4gIHZhciBsID0gbGluayhjdXJ2ZVJhZGlhbCQxKTtcbiAgbC5hbmdsZSA9IGwueCwgZGVsZXRlIGwueDtcbiAgbC5yYWRpdXMgPSBsLnksIGRlbGV0ZSBsLnk7XG4gIHJldHVybiBsO1xufVxuXG52YXIgY2lyY2xlID0ge1xuICBkcmF3OiBmdW5jdGlvbihjb250ZXh0LCBzaXplKSB7XG4gICAgdmFyIHIgPSBNYXRoLnNxcnQoc2l6ZSAvIHBpKTtcbiAgICBjb250ZXh0Lm1vdmVUbyhyLCAwKTtcbiAgICBjb250ZXh0LmFyYygwLCAwLCByLCAwLCB0YXUpO1xuICB9XG59O1xuXG52YXIgY3Jvc3MgPSB7XG4gIGRyYXc6IGZ1bmN0aW9uKGNvbnRleHQsIHNpemUpIHtcbiAgICB2YXIgciA9IE1hdGguc3FydChzaXplIC8gNSkgLyAyO1xuICAgIGNvbnRleHQubW92ZVRvKC0zICogciwgLXIpO1xuICAgIGNvbnRleHQubGluZVRvKC1yLCAtcik7XG4gICAgY29udGV4dC5saW5lVG8oLXIsIC0zICogcik7XG4gICAgY29udGV4dC5saW5lVG8ociwgLTMgKiByKTtcbiAgICBjb250ZXh0LmxpbmVUbyhyLCAtcik7XG4gICAgY29udGV4dC5saW5lVG8oMyAqIHIsIC1yKTtcbiAgICBjb250ZXh0LmxpbmVUbygzICogciwgcik7XG4gICAgY29udGV4dC5saW5lVG8ociwgcik7XG4gICAgY29udGV4dC5saW5lVG8ociwgMyAqIHIpO1xuICAgIGNvbnRleHQubGluZVRvKC1yLCAzICogcik7XG4gICAgY29udGV4dC5saW5lVG8oLXIsIHIpO1xuICAgIGNvbnRleHQubGluZVRvKC0zICogciwgcik7XG4gICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgfVxufTtcblxudmFyIHRhbjMwID0gTWF0aC5zcXJ0KDEgLyAzKTtcbnZhciB0YW4zMF8yID0gdGFuMzAgKiAyO1xuXG52YXIgZGlhbW9uZCA9IHtcbiAgZHJhdzogZnVuY3Rpb24oY29udGV4dCwgc2l6ZSkge1xuICAgIHZhciB5ID0gTWF0aC5zcXJ0KHNpemUgLyB0YW4zMF8yKSxcbiAgICAgICAgeCA9IHkgKiB0YW4zMDtcbiAgICBjb250ZXh0Lm1vdmVUbygwLCAteSk7XG4gICAgY29udGV4dC5saW5lVG8oeCwgMCk7XG4gICAgY29udGV4dC5saW5lVG8oMCwgeSk7XG4gICAgY29udGV4dC5saW5lVG8oLXgsIDApO1xuICAgIGNvbnRleHQuY2xvc2VQYXRoKCk7XG4gIH1cbn07XG5cbnZhciBrYSA9IDAuODkwODEzMDkxNTI5Mjg1MjI4MTA7XG52YXIga3IgPSBNYXRoLnNpbihwaSAvIDEwKSAvIE1hdGguc2luKDcgKiBwaSAvIDEwKTtcbnZhciBreCA9IE1hdGguc2luKHRhdSAvIDEwKSAqIGtyO1xudmFyIGt5ID0gLU1hdGguY29zKHRhdSAvIDEwKSAqIGtyO1xuXG52YXIgc3RhciA9IHtcbiAgZHJhdzogZnVuY3Rpb24oY29udGV4dCwgc2l6ZSkge1xuICAgIHZhciByID0gTWF0aC5zcXJ0KHNpemUgKiBrYSksXG4gICAgICAgIHggPSBreCAqIHIsXG4gICAgICAgIHkgPSBreSAqIHI7XG4gICAgY29udGV4dC5tb3ZlVG8oMCwgLXIpO1xuICAgIGNvbnRleHQubGluZVRvKHgsIHkpO1xuICAgIGZvciAodmFyIGkgPSAxOyBpIDwgNTsgKytpKSB7XG4gICAgICB2YXIgYSA9IHRhdSAqIGkgLyA1LFxuICAgICAgICAgIGMgPSBNYXRoLmNvcyhhKSxcbiAgICAgICAgICBzID0gTWF0aC5zaW4oYSk7XG4gICAgICBjb250ZXh0LmxpbmVUbyhzICogciwgLWMgKiByKTtcbiAgICAgIGNvbnRleHQubGluZVRvKGMgKiB4IC0gcyAqIHksIHMgKiB4ICsgYyAqIHkpO1xuICAgIH1cbiAgICBjb250ZXh0LmNsb3NlUGF0aCgpO1xuICB9XG59O1xuXG52YXIgc3F1YXJlID0ge1xuICBkcmF3OiBmdW5jdGlvbihjb250ZXh0LCBzaXplKSB7XG4gICAgdmFyIHcgPSBNYXRoLnNxcnQoc2l6ZSksXG4gICAgICAgIHggPSAtdyAvIDI7XG4gICAgY29udGV4dC5yZWN0KHgsIHgsIHcsIHcpO1xuICB9XG59O1xuXG52YXIgc3FydDMgPSBNYXRoLnNxcnQoMyk7XG5cbnZhciB0cmlhbmdsZSA9IHtcbiAgZHJhdzogZnVuY3Rpb24oY29udGV4dCwgc2l6ZSkge1xuICAgIHZhciB5ID0gLU1hdGguc3FydChzaXplIC8gKHNxcnQzICogMykpO1xuICAgIGNvbnRleHQubW92ZVRvKDAsIHkgKiAyKTtcbiAgICBjb250ZXh0LmxpbmVUbygtc3FydDMgKiB5LCAteSk7XG4gICAgY29udGV4dC5saW5lVG8oc3FydDMgKiB5LCAteSk7XG4gICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgfVxufTtcblxudmFyIGMgPSAtMC41O1xudmFyIHMgPSBNYXRoLnNxcnQoMykgLyAyO1xudmFyIGsgPSAxIC8gTWF0aC5zcXJ0KDEyKTtcbnZhciBhID0gKGsgLyAyICsgMSkgKiAzO1xuXG52YXIgd3llID0ge1xuICBkcmF3OiBmdW5jdGlvbihjb250ZXh0LCBzaXplKSB7XG4gICAgdmFyIHIgPSBNYXRoLnNxcnQoc2l6ZSAvIGEpLFxuICAgICAgICB4MCA9IHIgLyAyLFxuICAgICAgICB5MCA9IHIgKiBrLFxuICAgICAgICB4MSA9IHgwLFxuICAgICAgICB5MSA9IHIgKiBrICsgcixcbiAgICAgICAgeDIgPSAteDEsXG4gICAgICAgIHkyID0geTE7XG4gICAgY29udGV4dC5tb3ZlVG8oeDAsIHkwKTtcbiAgICBjb250ZXh0LmxpbmVUbyh4MSwgeTEpO1xuICAgIGNvbnRleHQubGluZVRvKHgyLCB5Mik7XG4gICAgY29udGV4dC5saW5lVG8oYyAqIHgwIC0gcyAqIHkwLCBzICogeDAgKyBjICogeTApO1xuICAgIGNvbnRleHQubGluZVRvKGMgKiB4MSAtIHMgKiB5MSwgcyAqIHgxICsgYyAqIHkxKTtcbiAgICBjb250ZXh0LmxpbmVUbyhjICogeDIgLSBzICogeTIsIHMgKiB4MiArIGMgKiB5Mik7XG4gICAgY29udGV4dC5saW5lVG8oYyAqIHgwICsgcyAqIHkwLCBjICogeTAgLSBzICogeDApO1xuICAgIGNvbnRleHQubGluZVRvKGMgKiB4MSArIHMgKiB5MSwgYyAqIHkxIC0gcyAqIHgxKTtcbiAgICBjb250ZXh0LmxpbmVUbyhjICogeDIgKyBzICogeTIsIGMgKiB5MiAtIHMgKiB4Mik7XG4gICAgY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgfVxufTtcblxudmFyIHN5bWJvbHMgPSBbXG4gIGNpcmNsZSxcbiAgY3Jvc3MsXG4gIGRpYW1vbmQsXG4gIHNxdWFyZSxcbiAgc3RhcixcbiAgdHJpYW5nbGUsXG4gIHd5ZVxuXTtcblxudmFyIHN5bWJvbCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgdHlwZSA9IGNvbnN0YW50KGNpcmNsZSksXG4gICAgICBzaXplID0gY29uc3RhbnQoNjQpLFxuICAgICAgY29udGV4dCA9IG51bGw7XG5cbiAgZnVuY3Rpb24gc3ltYm9sKCkge1xuICAgIHZhciBidWZmZXI7XG4gICAgaWYgKCFjb250ZXh0KSBjb250ZXh0ID0gYnVmZmVyID0gZDNQYXRoLnBhdGgoKTtcbiAgICB0eXBlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykuZHJhdyhjb250ZXh0LCArc2l6ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpKTtcbiAgICBpZiAoYnVmZmVyKSByZXR1cm4gY29udGV4dCA9IG51bGwsIGJ1ZmZlciArIFwiXCIgfHwgbnVsbDtcbiAgfVxuXG4gIHN5bWJvbC50eXBlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHR5cGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KF8pLCBzeW1ib2wpIDogdHlwZTtcbiAgfTtcblxuICBzeW1ib2wuc2l6ZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/IChzaXplID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIHN5bWJvbCkgOiBzaXplO1xuICB9O1xuXG4gIHN5bWJvbC5jb250ZXh0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbnRleHQgPSBfID09IG51bGwgPyBudWxsIDogXywgc3ltYm9sKSA6IGNvbnRleHQ7XG4gIH07XG5cbiAgcmV0dXJuIHN5bWJvbDtcbn07XG5cbnZhciBub29wID0gZnVuY3Rpb24oKSB7fTtcblxuZnVuY3Rpb24gcG9pbnQodGhhdCwgeCwgeSkge1xuICB0aGF0Ll9jb250ZXh0LmJlemllckN1cnZlVG8oXG4gICAgKDIgKiB0aGF0Ll94MCArIHRoYXQuX3gxKSAvIDMsXG4gICAgKDIgKiB0aGF0Ll95MCArIHRoYXQuX3kxKSAvIDMsXG4gICAgKHRoYXQuX3gwICsgMiAqIHRoYXQuX3gxKSAvIDMsXG4gICAgKHRoYXQuX3kwICsgMiAqIHRoYXQuX3kxKSAvIDMsXG4gICAgKHRoYXQuX3gwICsgNCAqIHRoYXQuX3gxICsgeCkgLyA2LFxuICAgICh0aGF0Ll95MCArIDQgKiB0aGF0Ll95MSArIHkpIC8gNlxuICApO1xufVxuXG5mdW5jdGlvbiBCYXNpcyhjb250ZXh0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xufVxuXG5CYXNpcy5wcm90b3R5cGUgPSB7XG4gIGFyZWFTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IDA7XG4gIH0sXG4gIGFyZWFFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSBOYU47XG4gIH0sXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IE5hTjtcbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMzogcG9pbnQodGhpcywgdGhpcy5feDEsIHRoaXMuX3kxKTsgLy8gcHJvY2VlZFxuICAgICAgY2FzZSAyOiB0aGlzLl9jb250ZXh0LmxpbmVUbyh0aGlzLl94MSwgdGhpcy5feTEpOyBicmVhaztcbiAgICB9XG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgdGhpcy5fcG9pbnQgPT09IDEpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDA6IHRoaXMuX3BvaW50ID0gMTsgdGhpcy5fbGluZSA/IHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8oeCwgeSk7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IGJyZWFrO1xuICAgICAgY2FzZSAyOiB0aGlzLl9wb2ludCA9IDM7IHRoaXMuX2NvbnRleHQubGluZVRvKCg1ICogdGhpcy5feDAgKyB0aGlzLl94MSkgLyA2LCAoNSAqIHRoaXMuX3kwICsgdGhpcy5feTEpIC8gNik7IC8vIHByb2NlZWRcbiAgICAgIGRlZmF1bHQ6IHBvaW50KHRoaXMsIHgsIHkpOyBicmVhaztcbiAgICB9XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0geTtcbiAgfVxufTtcblxudmFyIGJhc2lzID0gZnVuY3Rpb24oY29udGV4dCkge1xuICByZXR1cm4gbmV3IEJhc2lzKGNvbnRleHQpO1xufTtcblxuZnVuY3Rpb24gQmFzaXNDbG9zZWQoY29udGV4dCkge1xuICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbn1cblxuQmFzaXNDbG9zZWQucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IG5vb3AsXG4gIGFyZWFFbmQ6IG5vb3AsXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSA9IHRoaXMuX3gyID0gdGhpcy5feDMgPSB0aGlzLl94NCA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gdGhpcy5feTMgPSB0aGlzLl95NCA9IE5hTjtcbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMToge1xuICAgICAgICB0aGlzLl9jb250ZXh0Lm1vdmVUbyh0aGlzLl94MiwgdGhpcy5feTIpO1xuICAgICAgICB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgMjoge1xuICAgICAgICB0aGlzLl9jb250ZXh0Lm1vdmVUbygodGhpcy5feDIgKyAyICogdGhpcy5feDMpIC8gMywgKHRoaXMuX3kyICsgMiAqIHRoaXMuX3kzKSAvIDMpO1xuICAgICAgICB0aGlzLl9jb250ZXh0LmxpbmVUbygodGhpcy5feDMgKyAyICogdGhpcy5feDIpIC8gMywgKHRoaXMuX3kzICsgMiAqIHRoaXMuX3kyKSAvIDMpO1xuICAgICAgICB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgMzoge1xuICAgICAgICB0aGlzLnBvaW50KHRoaXMuX3gyLCB0aGlzLl95Mik7XG4gICAgICAgIHRoaXMucG9pbnQodGhpcy5feDMsIHRoaXMuX3kzKTtcbiAgICAgICAgdGhpcy5wb2ludCh0aGlzLl94NCwgdGhpcy5feTQpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgeCA9ICt4LCB5ID0gK3k7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAwOiB0aGlzLl9wb2ludCA9IDE7IHRoaXMuX3gyID0geCwgdGhpcy5feTIgPSB5OyBicmVhaztcbiAgICAgIGNhc2UgMTogdGhpcy5fcG9pbnQgPSAyOyB0aGlzLl94MyA9IHgsIHRoaXMuX3kzID0geTsgYnJlYWs7XG4gICAgICBjYXNlIDI6IHRoaXMuX3BvaW50ID0gMzsgdGhpcy5feDQgPSB4LCB0aGlzLl95NCA9IHk7IHRoaXMuX2NvbnRleHQubW92ZVRvKCh0aGlzLl94MCArIDQgKiB0aGlzLl94MSArIHgpIC8gNiwgKHRoaXMuX3kwICsgNCAqIHRoaXMuX3kxICsgeSkgLyA2KTsgYnJlYWs7XG4gICAgICBkZWZhdWx0OiBwb2ludCh0aGlzLCB4LCB5KTsgYnJlYWs7XG4gICAgfVxuICAgIHRoaXMuX3gwID0gdGhpcy5feDEsIHRoaXMuX3gxID0geDtcbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxLCB0aGlzLl95MSA9IHk7XG4gIH1cbn07XG5cbnZhciBiYXNpc0Nsb3NlZCA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcbiAgcmV0dXJuIG5ldyBCYXNpc0Nsb3NlZChjb250ZXh0KTtcbn07XG5cbmZ1bmN0aW9uIEJhc2lzT3Blbihjb250ZXh0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xufVxuXG5CYXNpc09wZW4ucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPVxuICAgIHRoaXMuX3kwID0gdGhpcy5feTEgPSBOYU47XG4gICAgdGhpcy5fcG9pbnQgPSAwO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5fbGluZSB8fCAodGhpcy5fbGluZSAhPT0gMCAmJiB0aGlzLl9wb2ludCA9PT0gMykpIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgdGhpcy5fbGluZSA9IDEgLSB0aGlzLl9saW5lO1xuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyBicmVhaztcbiAgICAgIGNhc2UgMTogdGhpcy5fcG9pbnQgPSAyOyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyB2YXIgeDAgPSAodGhpcy5feDAgKyA0ICogdGhpcy5feDEgKyB4KSAvIDYsIHkwID0gKHRoaXMuX3kwICsgNCAqIHRoaXMuX3kxICsgeSkgLyA2OyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8oeDAsIHkwKSA6IHRoaXMuX2NvbnRleHQubW92ZVRvKHgwLCB5MCk7IGJyZWFrO1xuICAgICAgY2FzZSAzOiB0aGlzLl9wb2ludCA9IDQ7IC8vIHByb2NlZWRcbiAgICAgIGRlZmF1bHQ6IHBvaW50KHRoaXMsIHgsIHkpOyBicmVhaztcbiAgICB9XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0geTtcbiAgfVxufTtcblxudmFyIGJhc2lzT3BlbiA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcbiAgcmV0dXJuIG5ldyBCYXNpc09wZW4oY29udGV4dCk7XG59O1xuXG5mdW5jdGlvbiBCdW5kbGUoY29udGV4dCwgYmV0YSkge1xuICB0aGlzLl9iYXNpcyA9IG5ldyBCYXNpcyhjb250ZXh0KTtcbiAgdGhpcy5fYmV0YSA9IGJldGE7XG59XG5cbkJ1bmRsZS5wcm90b3R5cGUgPSB7XG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feCA9IFtdO1xuICAgIHRoaXMuX3kgPSBbXTtcbiAgICB0aGlzLl9iYXNpcy5saW5lU3RhcnQoKTtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHggPSB0aGlzLl94LFxuICAgICAgICB5ID0gdGhpcy5feSxcbiAgICAgICAgaiA9IHgubGVuZ3RoIC0gMTtcblxuICAgIGlmIChqID4gMCkge1xuICAgICAgdmFyIHgwID0geFswXSxcbiAgICAgICAgICB5MCA9IHlbMF0sXG4gICAgICAgICAgZHggPSB4W2pdIC0geDAsXG4gICAgICAgICAgZHkgPSB5W2pdIC0geTAsXG4gICAgICAgICAgaSA9IC0xLFxuICAgICAgICAgIHQ7XG5cbiAgICAgIHdoaWxlICgrK2kgPD0gaikge1xuICAgICAgICB0ID0gaSAvIGo7XG4gICAgICAgIHRoaXMuX2Jhc2lzLnBvaW50KFxuICAgICAgICAgIHRoaXMuX2JldGEgKiB4W2ldICsgKDEgLSB0aGlzLl9iZXRhKSAqICh4MCArIHQgKiBkeCksXG4gICAgICAgICAgdGhpcy5fYmV0YSAqIHlbaV0gKyAoMSAtIHRoaXMuX2JldGEpICogKHkwICsgdCAqIGR5KVxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX3ggPSB0aGlzLl95ID0gbnVsbDtcbiAgICB0aGlzLl9iYXNpcy5saW5lRW5kKCk7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdGhpcy5feC5wdXNoKCt4KTtcbiAgICB0aGlzLl95LnB1c2goK3kpO1xuICB9XG59O1xuXG52YXIgYnVuZGxlID0gKChmdW5jdGlvbiBjdXN0b20oYmV0YSkge1xuXG4gIGZ1bmN0aW9uIGJ1bmRsZShjb250ZXh0KSB7XG4gICAgcmV0dXJuIGJldGEgPT09IDEgPyBuZXcgQmFzaXMoY29udGV4dCkgOiBuZXcgQnVuZGxlKGNvbnRleHQsIGJldGEpO1xuICB9XG5cbiAgYnVuZGxlLmJldGEgPSBmdW5jdGlvbihiZXRhKSB7XG4gICAgcmV0dXJuIGN1c3RvbSgrYmV0YSk7XG4gIH07XG5cbiAgcmV0dXJuIGJ1bmRsZTtcbn0pKSgwLjg1KTtcblxuZnVuY3Rpb24gcG9pbnQkMSh0aGF0LCB4LCB5KSB7XG4gIHRoYXQuX2NvbnRleHQuYmV6aWVyQ3VydmVUbyhcbiAgICB0aGF0Ll94MSArIHRoYXQuX2sgKiAodGhhdC5feDIgLSB0aGF0Ll94MCksXG4gICAgdGhhdC5feTEgKyB0aGF0Ll9rICogKHRoYXQuX3kyIC0gdGhhdC5feTApLFxuICAgIHRoYXQuX3gyICsgdGhhdC5fayAqICh0aGF0Ll94MSAtIHgpLFxuICAgIHRoYXQuX3kyICsgdGhhdC5fayAqICh0aGF0Ll95MSAtIHkpLFxuICAgIHRoYXQuX3gyLFxuICAgIHRoYXQuX3kyXG4gICk7XG59XG5cbmZ1bmN0aW9uIENhcmRpbmFsKGNvbnRleHQsIHRlbnNpb24pIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX2sgPSAoMSAtIHRlbnNpb24pIC8gNjtcbn1cblxuQ2FyZGluYWwucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gTmFOO1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAyOiB0aGlzLl9jb250ZXh0LmxpbmVUbyh0aGlzLl94MiwgdGhpcy5feTIpOyBicmVhaztcbiAgICAgIGNhc2UgMzogcG9pbnQkMSh0aGlzLCB0aGlzLl94MSwgdGhpcy5feTEpOyBicmVhaztcbiAgICB9XG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgdGhpcy5fcG9pbnQgPT09IDEpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDA6IHRoaXMuX3BvaW50ID0gMTsgdGhpcy5fbGluZSA/IHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8oeCwgeSk7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IHRoaXMuX3gxID0geCwgdGhpcy5feTEgPSB5OyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyAvLyBwcm9jZWVkXG4gICAgICBkZWZhdWx0OiBwb2ludCQxKHRoaXMsIHgsIHkpOyBicmVhaztcbiAgICB9XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB0aGlzLl94MiwgdGhpcy5feDIgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0gdGhpcy5feTIsIHRoaXMuX3kyID0geTtcbiAgfVxufTtcblxudmFyIGNhcmRpbmFsID0gKChmdW5jdGlvbiBjdXN0b20odGVuc2lvbikge1xuXG4gIGZ1bmN0aW9uIGNhcmRpbmFsKGNvbnRleHQpIHtcbiAgICByZXR1cm4gbmV3IENhcmRpbmFsKGNvbnRleHQsIHRlbnNpb24pO1xuICB9XG5cbiAgY2FyZGluYWwudGVuc2lvbiA9IGZ1bmN0aW9uKHRlbnNpb24pIHtcbiAgICByZXR1cm4gY3VzdG9tKCt0ZW5zaW9uKTtcbiAgfTtcblxuICByZXR1cm4gY2FyZGluYWw7XG59KSkoMCk7XG5cbmZ1bmN0aW9uIENhcmRpbmFsQ2xvc2VkKGNvbnRleHQsIHRlbnNpb24pIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX2sgPSAoMSAtIHRlbnNpb24pIC8gNjtcbn1cblxuQ2FyZGluYWxDbG9zZWQucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IG5vb3AsXG4gIGFyZWFFbmQ6IG5vb3AsXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSA9IHRoaXMuX3gyID0gdGhpcy5feDMgPSB0aGlzLl94NCA9IHRoaXMuX3g1ID1cbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxID0gdGhpcy5feTIgPSB0aGlzLl95MyA9IHRoaXMuX3k0ID0gdGhpcy5feTUgPSBOYU47XG4gICAgdGhpcy5fcG9pbnQgPSAwO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDE6IHtcbiAgICAgICAgdGhpcy5fY29udGV4dC5tb3ZlVG8odGhpcy5feDMsIHRoaXMuX3kzKTtcbiAgICAgICAgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDI6IHtcbiAgICAgICAgdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feDMsIHRoaXMuX3kzKTtcbiAgICAgICAgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlIDM6IHtcbiAgICAgICAgdGhpcy5wb2ludCh0aGlzLl94MywgdGhpcy5feTMpO1xuICAgICAgICB0aGlzLnBvaW50KHRoaXMuX3g0LCB0aGlzLl95NCk7XG4gICAgICAgIHRoaXMucG9pbnQodGhpcy5feDUsIHRoaXMuX3k1KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl94MyA9IHgsIHRoaXMuX3kzID0geTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgdGhpcy5fY29udGV4dC5tb3ZlVG8odGhpcy5feDQgPSB4LCB0aGlzLl95NCA9IHkpOyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyB0aGlzLl94NSA9IHgsIHRoaXMuX3k1ID0geTsgYnJlYWs7XG4gICAgICBkZWZhdWx0OiBwb2ludCQxKHRoaXMsIHgsIHkpOyBicmVhaztcbiAgICB9XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB0aGlzLl94MiwgdGhpcy5feDIgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0gdGhpcy5feTIsIHRoaXMuX3kyID0geTtcbiAgfVxufTtcblxudmFyIGNhcmRpbmFsQ2xvc2VkID0gKChmdW5jdGlvbiBjdXN0b20odGVuc2lvbikge1xuXG4gIGZ1bmN0aW9uIGNhcmRpbmFsKGNvbnRleHQpIHtcbiAgICByZXR1cm4gbmV3IENhcmRpbmFsQ2xvc2VkKGNvbnRleHQsIHRlbnNpb24pO1xuICB9XG5cbiAgY2FyZGluYWwudGVuc2lvbiA9IGZ1bmN0aW9uKHRlbnNpb24pIHtcbiAgICByZXR1cm4gY3VzdG9tKCt0ZW5zaW9uKTtcbiAgfTtcblxuICByZXR1cm4gY2FyZGluYWw7XG59KSkoMCk7XG5cbmZ1bmN0aW9uIENhcmRpbmFsT3Blbihjb250ZXh0LCB0ZW5zaW9uKSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xuICB0aGlzLl9rID0gKDEgLSB0ZW5zaW9uKSAvIDY7XG59XG5cbkNhcmRpbmFsT3Blbi5wcm90b3R5cGUgPSB7XG4gIGFyZWFTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IDA7XG4gIH0sXG4gIGFyZWFFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSBOYU47XG4gIH0sXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSA9IHRoaXMuX3gyID1cbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxID0gdGhpcy5feTIgPSBOYU47XG4gICAgdGhpcy5fcG9pbnQgPSAwO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5fbGluZSB8fCAodGhpcy5fbGluZSAhPT0gMCAmJiB0aGlzLl9wb2ludCA9PT0gMykpIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgdGhpcy5fbGluZSA9IDEgLSB0aGlzLl9saW5lO1xuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyBicmVhaztcbiAgICAgIGNhc2UgMTogdGhpcy5fcG9pbnQgPSAyOyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feDIsIHRoaXMuX3kyKSA6IHRoaXMuX2NvbnRleHQubW92ZVRvKHRoaXMuX3gyLCB0aGlzLl95Mik7IGJyZWFrO1xuICAgICAgY2FzZSAzOiB0aGlzLl9wb2ludCA9IDQ7IC8vIHByb2NlZWRcbiAgICAgIGRlZmF1bHQ6IHBvaW50JDEodGhpcywgeCwgeSk7IGJyZWFrO1xuICAgIH1cbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxLCB0aGlzLl94MSA9IHRoaXMuX3gyLCB0aGlzLl94MiA9IHg7XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSwgdGhpcy5feTEgPSB0aGlzLl95MiwgdGhpcy5feTIgPSB5O1xuICB9XG59O1xuXG52YXIgY2FyZGluYWxPcGVuID0gKChmdW5jdGlvbiBjdXN0b20odGVuc2lvbikge1xuXG4gIGZ1bmN0aW9uIGNhcmRpbmFsKGNvbnRleHQpIHtcbiAgICByZXR1cm4gbmV3IENhcmRpbmFsT3Blbihjb250ZXh0LCB0ZW5zaW9uKTtcbiAgfVxuXG4gIGNhcmRpbmFsLnRlbnNpb24gPSBmdW5jdGlvbih0ZW5zaW9uKSB7XG4gICAgcmV0dXJuIGN1c3RvbSgrdGVuc2lvbik7XG4gIH07XG5cbiAgcmV0dXJuIGNhcmRpbmFsO1xufSkpKDApO1xuXG5mdW5jdGlvbiBwb2ludCQyKHRoYXQsIHgsIHkpIHtcbiAgdmFyIHgxID0gdGhhdC5feDEsXG4gICAgICB5MSA9IHRoYXQuX3kxLFxuICAgICAgeDIgPSB0aGF0Ll94MixcbiAgICAgIHkyID0gdGhhdC5feTI7XG5cbiAgaWYgKHRoYXQuX2wwMV9hID4gZXBzaWxvbikge1xuICAgIHZhciBhID0gMiAqIHRoYXQuX2wwMV8yYSArIDMgKiB0aGF0Ll9sMDFfYSAqIHRoYXQuX2wxMl9hICsgdGhhdC5fbDEyXzJhLFxuICAgICAgICBuID0gMyAqIHRoYXQuX2wwMV9hICogKHRoYXQuX2wwMV9hICsgdGhhdC5fbDEyX2EpO1xuICAgIHgxID0gKHgxICogYSAtIHRoYXQuX3gwICogdGhhdC5fbDEyXzJhICsgdGhhdC5feDIgKiB0aGF0Ll9sMDFfMmEpIC8gbjtcbiAgICB5MSA9ICh5MSAqIGEgLSB0aGF0Ll95MCAqIHRoYXQuX2wxMl8yYSArIHRoYXQuX3kyICogdGhhdC5fbDAxXzJhKSAvIG47XG4gIH1cblxuICBpZiAodGhhdC5fbDIzX2EgPiBlcHNpbG9uKSB7XG4gICAgdmFyIGIgPSAyICogdGhhdC5fbDIzXzJhICsgMyAqIHRoYXQuX2wyM19hICogdGhhdC5fbDEyX2EgKyB0aGF0Ll9sMTJfMmEsXG4gICAgICAgIG0gPSAzICogdGhhdC5fbDIzX2EgKiAodGhhdC5fbDIzX2EgKyB0aGF0Ll9sMTJfYSk7XG4gICAgeDIgPSAoeDIgKiBiICsgdGhhdC5feDEgKiB0aGF0Ll9sMjNfMmEgLSB4ICogdGhhdC5fbDEyXzJhKSAvIG07XG4gICAgeTIgPSAoeTIgKiBiICsgdGhhdC5feTEgKiB0aGF0Ll9sMjNfMmEgLSB5ICogdGhhdC5fbDEyXzJhKSAvIG07XG4gIH1cblxuICB0aGF0Ll9jb250ZXh0LmJlemllckN1cnZlVG8oeDEsIHkxLCB4MiwgeTIsIHRoYXQuX3gyLCB0aGF0Ll95Mik7XG59XG5cbmZ1bmN0aW9uIENhdG11bGxSb20oY29udGV4dCwgYWxwaGEpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX2FscGhhID0gYWxwaGE7XG59XG5cbkNhdG11bGxSb20ucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gTmFOO1xuICAgIHRoaXMuX2wwMV9hID0gdGhpcy5fbDEyX2EgPSB0aGlzLl9sMjNfYSA9XG4gICAgdGhpcy5fbDAxXzJhID0gdGhpcy5fbDEyXzJhID0gdGhpcy5fbDIzXzJhID1cbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMjogdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feDIsIHRoaXMuX3kyKTsgYnJlYWs7XG4gICAgICBjYXNlIDM6IHRoaXMucG9pbnQodGhpcy5feDIsIHRoaXMuX3kyKTsgYnJlYWs7XG4gICAgfVxuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIHRoaXMuX3BvaW50ID09PSAxKSkgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB0aGlzLl9saW5lID0gMSAtIHRoaXMuX2xpbmU7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgeCA9ICt4LCB5ID0gK3k7XG5cbiAgICBpZiAodGhpcy5fcG9pbnQpIHtcbiAgICAgIHZhciB4MjMgPSB0aGlzLl94MiAtIHgsXG4gICAgICAgICAgeTIzID0gdGhpcy5feTIgLSB5O1xuICAgICAgdGhpcy5fbDIzX2EgPSBNYXRoLnNxcnQodGhpcy5fbDIzXzJhID0gTWF0aC5wb3coeDIzICogeDIzICsgeTIzICogeTIzLCB0aGlzLl9hbHBoYSkpO1xuICAgIH1cblxuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSkgOiB0aGlzLl9jb250ZXh0Lm1vdmVUbyh4LCB5KTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgYnJlYWs7XG4gICAgICBjYXNlIDI6IHRoaXMuX3BvaW50ID0gMzsgLy8gcHJvY2VlZFxuICAgICAgZGVmYXVsdDogcG9pbnQkMih0aGlzLCB4LCB5KTsgYnJlYWs7XG4gICAgfVxuXG4gICAgdGhpcy5fbDAxX2EgPSB0aGlzLl9sMTJfYSwgdGhpcy5fbDEyX2EgPSB0aGlzLl9sMjNfYTtcbiAgICB0aGlzLl9sMDFfMmEgPSB0aGlzLl9sMTJfMmEsIHRoaXMuX2wxMl8yYSA9IHRoaXMuX2wyM18yYTtcbiAgICB0aGlzLl94MCA9IHRoaXMuX3gxLCB0aGlzLl94MSA9IHRoaXMuX3gyLCB0aGlzLl94MiA9IHg7XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSwgdGhpcy5feTEgPSB0aGlzLl95MiwgdGhpcy5feTIgPSB5O1xuICB9XG59O1xuXG52YXIgY2F0bXVsbFJvbSA9ICgoZnVuY3Rpb24gY3VzdG9tKGFscGhhKSB7XG5cbiAgZnVuY3Rpb24gY2F0bXVsbFJvbShjb250ZXh0KSB7XG4gICAgcmV0dXJuIGFscGhhID8gbmV3IENhdG11bGxSb20oY29udGV4dCwgYWxwaGEpIDogbmV3IENhcmRpbmFsKGNvbnRleHQsIDApO1xuICB9XG5cbiAgY2F0bXVsbFJvbS5hbHBoYSA9IGZ1bmN0aW9uKGFscGhhKSB7XG4gICAgcmV0dXJuIGN1c3RvbSgrYWxwaGEpO1xuICB9O1xuXG4gIHJldHVybiBjYXRtdWxsUm9tO1xufSkpKDAuNSk7XG5cbmZ1bmN0aW9uIENhdG11bGxSb21DbG9zZWQoY29udGV4dCwgYWxwaGEpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX2FscGhhID0gYWxwaGE7XG59XG5cbkNhdG11bGxSb21DbG9zZWQucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IG5vb3AsXG4gIGFyZWFFbmQ6IG5vb3AsXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSA9IHRoaXMuX3gyID0gdGhpcy5feDMgPSB0aGlzLl94NCA9IHRoaXMuX3g1ID1cbiAgICB0aGlzLl95MCA9IHRoaXMuX3kxID0gdGhpcy5feTIgPSB0aGlzLl95MyA9IHRoaXMuX3k0ID0gdGhpcy5feTUgPSBOYU47XG4gICAgdGhpcy5fbDAxX2EgPSB0aGlzLl9sMTJfYSA9IHRoaXMuX2wyM19hID1cbiAgICB0aGlzLl9sMDFfMmEgPSB0aGlzLl9sMTJfMmEgPSB0aGlzLl9sMjNfMmEgPVxuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAxOiB7XG4gICAgICAgIHRoaXMuX2NvbnRleHQubW92ZVRvKHRoaXMuX3gzLCB0aGlzLl95Myk7XG4gICAgICAgIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAyOiB7XG4gICAgICAgIHRoaXMuX2NvbnRleHQubGluZVRvKHRoaXMuX3gzLCB0aGlzLl95Myk7XG4gICAgICAgIHRoaXMuX2NvbnRleHQuY2xvc2VQYXRoKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgY2FzZSAzOiB7XG4gICAgICAgIHRoaXMucG9pbnQodGhpcy5feDMsIHRoaXMuX3kzKTtcbiAgICAgICAgdGhpcy5wb2ludCh0aGlzLl94NCwgdGhpcy5feTQpO1xuICAgICAgICB0aGlzLnBvaW50KHRoaXMuX3g1LCB0aGlzLl95NSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgcG9pbnQ6IGZ1bmN0aW9uKHgsIHkpIHtcbiAgICB4ID0gK3gsIHkgPSAreTtcblxuICAgIGlmICh0aGlzLl9wb2ludCkge1xuICAgICAgdmFyIHgyMyA9IHRoaXMuX3gyIC0geCxcbiAgICAgICAgICB5MjMgPSB0aGlzLl95MiAtIHk7XG4gICAgICB0aGlzLl9sMjNfYSA9IE1hdGguc3FydCh0aGlzLl9sMjNfMmEgPSBNYXRoLnBvdyh4MjMgKiB4MjMgKyB5MjMgKiB5MjMsIHRoaXMuX2FscGhhKSk7XG4gICAgfVxuXG4gICAgc3dpdGNoICh0aGlzLl9wb2ludCkge1xuICAgICAgY2FzZSAwOiB0aGlzLl9wb2ludCA9IDE7IHRoaXMuX3gzID0geCwgdGhpcy5feTMgPSB5OyBicmVhaztcbiAgICAgIGNhc2UgMTogdGhpcy5fcG9pbnQgPSAyOyB0aGlzLl9jb250ZXh0Lm1vdmVUbyh0aGlzLl94NCA9IHgsIHRoaXMuX3k0ID0geSk7IGJyZWFrO1xuICAgICAgY2FzZSAyOiB0aGlzLl9wb2ludCA9IDM7IHRoaXMuX3g1ID0geCwgdGhpcy5feTUgPSB5OyBicmVhaztcbiAgICAgIGRlZmF1bHQ6IHBvaW50JDIodGhpcywgeCwgeSk7IGJyZWFrO1xuICAgIH1cblxuICAgIHRoaXMuX2wwMV9hID0gdGhpcy5fbDEyX2EsIHRoaXMuX2wxMl9hID0gdGhpcy5fbDIzX2E7XG4gICAgdGhpcy5fbDAxXzJhID0gdGhpcy5fbDEyXzJhLCB0aGlzLl9sMTJfMmEgPSB0aGlzLl9sMjNfMmE7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB0aGlzLl94MiwgdGhpcy5feDIgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0gdGhpcy5feTIsIHRoaXMuX3kyID0geTtcbiAgfVxufTtcblxudmFyIGNhdG11bGxSb21DbG9zZWQgPSAoKGZ1bmN0aW9uIGN1c3RvbShhbHBoYSkge1xuXG4gIGZ1bmN0aW9uIGNhdG11bGxSb20oY29udGV4dCkge1xuICAgIHJldHVybiBhbHBoYSA/IG5ldyBDYXRtdWxsUm9tQ2xvc2VkKGNvbnRleHQsIGFscGhhKSA6IG5ldyBDYXJkaW5hbENsb3NlZChjb250ZXh0LCAwKTtcbiAgfVxuXG4gIGNhdG11bGxSb20uYWxwaGEgPSBmdW5jdGlvbihhbHBoYSkge1xuICAgIHJldHVybiBjdXN0b20oK2FscGhhKTtcbiAgfTtcblxuICByZXR1cm4gY2F0bXVsbFJvbTtcbn0pKSgwLjUpO1xuXG5mdW5jdGlvbiBDYXRtdWxsUm9tT3Blbihjb250ZXh0LCBhbHBoYSkge1xuICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbiAgdGhpcy5fYWxwaGEgPSBhbHBoYTtcbn1cblxuQ2F0bXVsbFJvbU9wZW4ucHJvdG90eXBlID0ge1xuICBhcmVhU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSAwO1xuICB9LFxuICBhcmVhRW5kOiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gTmFOO1xuICB9LFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3gwID0gdGhpcy5feDEgPSB0aGlzLl94MiA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9IHRoaXMuX3kyID0gTmFOO1xuICAgIHRoaXMuX2wwMV9hID0gdGhpcy5fbDEyX2EgPSB0aGlzLl9sMjNfYSA9XG4gICAgdGhpcy5fbDAxXzJhID0gdGhpcy5fbDEyXzJhID0gdGhpcy5fbDIzXzJhID1cbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIHRoaXMuX3BvaW50ID09PSAzKSkgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB0aGlzLl9saW5lID0gMSAtIHRoaXMuX2xpbmU7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgeCA9ICt4LCB5ID0gK3k7XG5cbiAgICBpZiAodGhpcy5fcG9pbnQpIHtcbiAgICAgIHZhciB4MjMgPSB0aGlzLl94MiAtIHgsXG4gICAgICAgICAgeTIzID0gdGhpcy5feTIgLSB5O1xuICAgICAgdGhpcy5fbDIzX2EgPSBNYXRoLnNxcnQodGhpcy5fbDIzXzJhID0gTWF0aC5wb3coeDIzICogeDIzICsgeTIzICogeTIzLCB0aGlzLl9hbHBoYSkpO1xuICAgIH1cblxuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyBicmVhaztcbiAgICAgIGNhc2UgMTogdGhpcy5fcG9pbnQgPSAyOyBicmVhaztcbiAgICAgIGNhc2UgMjogdGhpcy5fcG9pbnQgPSAzOyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feDIsIHRoaXMuX3kyKSA6IHRoaXMuX2NvbnRleHQubW92ZVRvKHRoaXMuX3gyLCB0aGlzLl95Mik7IGJyZWFrO1xuICAgICAgY2FzZSAzOiB0aGlzLl9wb2ludCA9IDQ7IC8vIHByb2NlZWRcbiAgICAgIGRlZmF1bHQ6IHBvaW50JDIodGhpcywgeCwgeSk7IGJyZWFrO1xuICAgIH1cblxuICAgIHRoaXMuX2wwMV9hID0gdGhpcy5fbDEyX2EsIHRoaXMuX2wxMl9hID0gdGhpcy5fbDIzX2E7XG4gICAgdGhpcy5fbDAxXzJhID0gdGhpcy5fbDEyXzJhLCB0aGlzLl9sMTJfMmEgPSB0aGlzLl9sMjNfMmE7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB0aGlzLl94MiwgdGhpcy5feDIgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0gdGhpcy5feTIsIHRoaXMuX3kyID0geTtcbiAgfVxufTtcblxudmFyIGNhdG11bGxSb21PcGVuID0gKChmdW5jdGlvbiBjdXN0b20oYWxwaGEpIHtcblxuICBmdW5jdGlvbiBjYXRtdWxsUm9tKGNvbnRleHQpIHtcbiAgICByZXR1cm4gYWxwaGEgPyBuZXcgQ2F0bXVsbFJvbU9wZW4oY29udGV4dCwgYWxwaGEpIDogbmV3IENhcmRpbmFsT3Blbihjb250ZXh0LCAwKTtcbiAgfVxuXG4gIGNhdG11bGxSb20uYWxwaGEgPSBmdW5jdGlvbihhbHBoYSkge1xuICAgIHJldHVybiBjdXN0b20oK2FscGhhKTtcbiAgfTtcblxuICByZXR1cm4gY2F0bXVsbFJvbTtcbn0pKSgwLjUpO1xuXG5mdW5jdGlvbiBMaW5lYXJDbG9zZWQoY29udGV4dCkge1xuICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbn1cblxuTGluZWFyQ2xvc2VkLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBub29wLFxuICBhcmVhRW5kOiBub29wLFxuICBsaW5lU3RhcnQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX3BvaW50ID0gMDtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgaWYgKHRoaXMuX3BvaW50KSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIGlmICh0aGlzLl9wb2ludCkgdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSk7XG4gICAgZWxzZSB0aGlzLl9wb2ludCA9IDEsIHRoaXMuX2NvbnRleHQubW92ZVRvKHgsIHkpO1xuICB9XG59O1xuXG52YXIgbGluZWFyQ2xvc2VkID0gZnVuY3Rpb24oY29udGV4dCkge1xuICByZXR1cm4gbmV3IExpbmVhckNsb3NlZChjb250ZXh0KTtcbn07XG5cbmZ1bmN0aW9uIHNpZ24oeCkge1xuICByZXR1cm4geCA8IDAgPyAtMSA6IDE7XG59XG5cbi8vIENhbGN1bGF0ZSB0aGUgc2xvcGVzIG9mIHRoZSB0YW5nZW50cyAoSGVybWl0ZS10eXBlIGludGVycG9sYXRpb24pIGJhc2VkIG9uXG4vLyB0aGUgZm9sbG93aW5nIHBhcGVyOiBTdGVmZmVuLCBNLiAxOTkwLiBBIFNpbXBsZSBNZXRob2QgZm9yIE1vbm90b25pY1xuLy8gSW50ZXJwb2xhdGlvbiBpbiBPbmUgRGltZW5zaW9uLiBBc3Ryb25vbXkgYW5kIEFzdHJvcGh5c2ljcywgVm9sLiAyMzksIE5PLlxuLy8gTk9WKElJKSwgUC4gNDQzLCAxOTkwLlxuZnVuY3Rpb24gc2xvcGUzKHRoYXQsIHgyLCB5Mikge1xuICB2YXIgaDAgPSB0aGF0Ll94MSAtIHRoYXQuX3gwLFxuICAgICAgaDEgPSB4MiAtIHRoYXQuX3gxLFxuICAgICAgczAgPSAodGhhdC5feTEgLSB0aGF0Ll95MCkgLyAoaDAgfHwgaDEgPCAwICYmIC0wKSxcbiAgICAgIHMxID0gKHkyIC0gdGhhdC5feTEpIC8gKGgxIHx8IGgwIDwgMCAmJiAtMCksXG4gICAgICBwID0gKHMwICogaDEgKyBzMSAqIGgwKSAvIChoMCArIGgxKTtcbiAgcmV0dXJuIChzaWduKHMwKSArIHNpZ24oczEpKSAqIE1hdGgubWluKE1hdGguYWJzKHMwKSwgTWF0aC5hYnMoczEpLCAwLjUgKiBNYXRoLmFicyhwKSkgfHwgMDtcbn1cblxuLy8gQ2FsY3VsYXRlIGEgb25lLXNpZGVkIHNsb3BlLlxuZnVuY3Rpb24gc2xvcGUyKHRoYXQsIHQpIHtcbiAgdmFyIGggPSB0aGF0Ll94MSAtIHRoYXQuX3gwO1xuICByZXR1cm4gaCA/ICgzICogKHRoYXQuX3kxIC0gdGhhdC5feTApIC8gaCAtIHQpIC8gMiA6IHQ7XG59XG5cbi8vIEFjY29yZGluZyB0byBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DdWJpY19IZXJtaXRlX3NwbGluZSNSZXByZXNlbnRhdGlvbnNcbi8vIFwieW91IGNhbiBleHByZXNzIGN1YmljIEhlcm1pdGUgaW50ZXJwb2xhdGlvbiBpbiB0ZXJtcyBvZiBjdWJpYyBCw6l6aWVyIGN1cnZlc1xuLy8gd2l0aCByZXNwZWN0IHRvIHRoZSBmb3VyIHZhbHVlcyBwMCwgcDAgKyBtMCAvIDMsIHAxIC0gbTEgLyAzLCBwMVwiLlxuZnVuY3Rpb24gcG9pbnQkMyh0aGF0LCB0MCwgdDEpIHtcbiAgdmFyIHgwID0gdGhhdC5feDAsXG4gICAgICB5MCA9IHRoYXQuX3kwLFxuICAgICAgeDEgPSB0aGF0Ll94MSxcbiAgICAgIHkxID0gdGhhdC5feTEsXG4gICAgICBkeCA9ICh4MSAtIHgwKSAvIDM7XG4gIHRoYXQuX2NvbnRleHQuYmV6aWVyQ3VydmVUbyh4MCArIGR4LCB5MCArIGR4ICogdDAsIHgxIC0gZHgsIHkxIC0gZHggKiB0MSwgeDEsIHkxKTtcbn1cblxuZnVuY3Rpb24gTW9ub3RvbmVYKGNvbnRleHQpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG59XG5cbk1vbm90b25lWC5wcm90b3R5cGUgPSB7XG4gIGFyZWFTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IDA7XG4gIH0sXG4gIGFyZWFFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSBOYU47XG4gIH0sXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSA9XG4gICAgdGhpcy5feTAgPSB0aGlzLl95MSA9XG4gICAgdGhpcy5fdDAgPSBOYU47XG4gICAgdGhpcy5fcG9pbnQgPSAwO1xuICB9LFxuICBsaW5lRW5kOiBmdW5jdGlvbigpIHtcbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDI6IHRoaXMuX2NvbnRleHQubGluZVRvKHRoaXMuX3gxLCB0aGlzLl95MSk7IGJyZWFrO1xuICAgICAgY2FzZSAzOiBwb2ludCQzKHRoaXMsIHRoaXMuX3QwLCBzbG9wZTIodGhpcywgdGhpcy5fdDApKTsgYnJlYWs7XG4gICAgfVxuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIHRoaXMuX3BvaW50ID09PSAxKSkgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTtcbiAgICB0aGlzLl9saW5lID0gMSAtIHRoaXMuX2xpbmU7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdmFyIHQxID0gTmFOO1xuXG4gICAgeCA9ICt4LCB5ID0gK3k7XG4gICAgaWYgKHggPT09IHRoaXMuX3gxICYmIHkgPT09IHRoaXMuX3kxKSByZXR1cm47IC8vIElnbm9yZSBjb2luY2lkZW50IHBvaW50cy5cbiAgICBzd2l0Y2ggKHRoaXMuX3BvaW50KSB7XG4gICAgICBjYXNlIDA6IHRoaXMuX3BvaW50ID0gMTsgdGhpcy5fbGluZSA/IHRoaXMuX2NvbnRleHQubGluZVRvKHgsIHkpIDogdGhpcy5fY29udGV4dC5tb3ZlVG8oeCwgeSk7IGJyZWFrO1xuICAgICAgY2FzZSAxOiB0aGlzLl9wb2ludCA9IDI7IGJyZWFrO1xuICAgICAgY2FzZSAyOiB0aGlzLl9wb2ludCA9IDM7IHBvaW50JDModGhpcywgc2xvcGUyKHRoaXMsIHQxID0gc2xvcGUzKHRoaXMsIHgsIHkpKSwgdDEpOyBicmVhaztcbiAgICAgIGRlZmF1bHQ6IHBvaW50JDModGhpcywgdGhpcy5fdDAsIHQxID0gc2xvcGUzKHRoaXMsIHgsIHkpKTsgYnJlYWs7XG4gICAgfVxuXG4gICAgdGhpcy5feDAgPSB0aGlzLl94MSwgdGhpcy5feDEgPSB4O1xuICAgIHRoaXMuX3kwID0gdGhpcy5feTEsIHRoaXMuX3kxID0geTtcbiAgICB0aGlzLl90MCA9IHQxO1xuICB9XG59O1xuXG5mdW5jdGlvbiBNb25vdG9uZVkoY29udGV4dCkge1xuICB0aGlzLl9jb250ZXh0ID0gbmV3IFJlZmxlY3RDb250ZXh0KGNvbnRleHQpO1xufVxuXG4oTW9ub3RvbmVZLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoTW9ub3RvbmVYLnByb3RvdHlwZSkpLnBvaW50ID0gZnVuY3Rpb24oeCwgeSkge1xuICBNb25vdG9uZVgucHJvdG90eXBlLnBvaW50LmNhbGwodGhpcywgeSwgeCk7XG59O1xuXG5mdW5jdGlvbiBSZWZsZWN0Q29udGV4dChjb250ZXh0KSB7XG4gIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xufVxuXG5SZWZsZWN0Q29udGV4dC5wcm90b3R5cGUgPSB7XG4gIG1vdmVUbzogZnVuY3Rpb24oeCwgeSkgeyB0aGlzLl9jb250ZXh0Lm1vdmVUbyh5LCB4KTsgfSxcbiAgY2xvc2VQYXRoOiBmdW5jdGlvbigpIHsgdGhpcy5fY29udGV4dC5jbG9zZVBhdGgoKTsgfSxcbiAgbGluZVRvOiBmdW5jdGlvbih4LCB5KSB7IHRoaXMuX2NvbnRleHQubGluZVRvKHksIHgpOyB9LFxuICBiZXppZXJDdXJ2ZVRvOiBmdW5jdGlvbih4MSwgeTEsIHgyLCB5MiwgeCwgeSkgeyB0aGlzLl9jb250ZXh0LmJlemllckN1cnZlVG8oeTEsIHgxLCB5MiwgeDIsIHksIHgpOyB9XG59O1xuXG5mdW5jdGlvbiBtb25vdG9uZVgoY29udGV4dCkge1xuICByZXR1cm4gbmV3IE1vbm90b25lWChjb250ZXh0KTtcbn1cblxuZnVuY3Rpb24gbW9ub3RvbmVZKGNvbnRleHQpIHtcbiAgcmV0dXJuIG5ldyBNb25vdG9uZVkoY29udGV4dCk7XG59XG5cbmZ1bmN0aW9uIE5hdHVyYWwoY29udGV4dCkge1xuICB0aGlzLl9jb250ZXh0ID0gY29udGV4dDtcbn1cblxuTmF0dXJhbC5wcm90b3R5cGUgPSB7XG4gIGFyZWFTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IDA7XG4gIH0sXG4gIGFyZWFFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuX2xpbmUgPSBOYU47XG4gIH0sXG4gIGxpbmVTdGFydDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5feCA9IFtdO1xuICAgIHRoaXMuX3kgPSBbXTtcbiAgfSxcbiAgbGluZUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdmFyIHggPSB0aGlzLl94LFxuICAgICAgICB5ID0gdGhpcy5feSxcbiAgICAgICAgbiA9IHgubGVuZ3RoO1xuXG4gICAgaWYgKG4pIHtcbiAgICAgIHRoaXMuX2xpbmUgPyB0aGlzLl9jb250ZXh0LmxpbmVUbyh4WzBdLCB5WzBdKSA6IHRoaXMuX2NvbnRleHQubW92ZVRvKHhbMF0sIHlbMF0pO1xuICAgICAgaWYgKG4gPT09IDIpIHtcbiAgICAgICAgdGhpcy5fY29udGV4dC5saW5lVG8oeFsxXSwgeVsxXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgcHggPSBjb250cm9sUG9pbnRzKHgpLFxuICAgICAgICAgICAgcHkgPSBjb250cm9sUG9pbnRzKHkpO1xuICAgICAgICBmb3IgKHZhciBpMCA9IDAsIGkxID0gMTsgaTEgPCBuOyArK2kwLCArK2kxKSB7XG4gICAgICAgICAgdGhpcy5fY29udGV4dC5iZXppZXJDdXJ2ZVRvKHB4WzBdW2kwXSwgcHlbMF1baTBdLCBweFsxXVtpMF0sIHB5WzFdW2kwXSwgeFtpMV0sIHlbaTFdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLl9saW5lIHx8ICh0aGlzLl9saW5lICE9PSAwICYmIG4gPT09IDEpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIHRoaXMuX2xpbmUgPSAxIC0gdGhpcy5fbGluZTtcbiAgICB0aGlzLl94ID0gdGhpcy5feSA9IG51bGw7XG4gIH0sXG4gIHBvaW50OiBmdW5jdGlvbih4LCB5KSB7XG4gICAgdGhpcy5feC5wdXNoKCt4KTtcbiAgICB0aGlzLl95LnB1c2goK3kpO1xuICB9XG59O1xuXG4vLyBTZWUgaHR0cHM6Ly93d3cucGFydGljbGVpbmNlbGwuY29tLzIwMTIvYmV6aWVyLXNwbGluZXMvIGZvciBkZXJpdmF0aW9uLlxuZnVuY3Rpb24gY29udHJvbFBvaW50cyh4KSB7XG4gIHZhciBpLFxuICAgICAgbiA9IHgubGVuZ3RoIC0gMSxcbiAgICAgIG0sXG4gICAgICBhID0gbmV3IEFycmF5KG4pLFxuICAgICAgYiA9IG5ldyBBcnJheShuKSxcbiAgICAgIHIgPSBuZXcgQXJyYXkobik7XG4gIGFbMF0gPSAwLCBiWzBdID0gMiwgclswXSA9IHhbMF0gKyAyICogeFsxXTtcbiAgZm9yIChpID0gMTsgaSA8IG4gLSAxOyArK2kpIGFbaV0gPSAxLCBiW2ldID0gNCwgcltpXSA9IDQgKiB4W2ldICsgMiAqIHhbaSArIDFdO1xuICBhW24gLSAxXSA9IDIsIGJbbiAtIDFdID0gNywgcltuIC0gMV0gPSA4ICogeFtuIC0gMV0gKyB4W25dO1xuICBmb3IgKGkgPSAxOyBpIDwgbjsgKytpKSBtID0gYVtpXSAvIGJbaSAtIDFdLCBiW2ldIC09IG0sIHJbaV0gLT0gbSAqIHJbaSAtIDFdO1xuICBhW24gLSAxXSA9IHJbbiAtIDFdIC8gYltuIC0gMV07XG4gIGZvciAoaSA9IG4gLSAyOyBpID49IDA7IC0taSkgYVtpXSA9IChyW2ldIC0gYVtpICsgMV0pIC8gYltpXTtcbiAgYltuIC0gMV0gPSAoeFtuXSArIGFbbiAtIDFdKSAvIDI7XG4gIGZvciAoaSA9IDA7IGkgPCBuIC0gMTsgKytpKSBiW2ldID0gMiAqIHhbaSArIDFdIC0gYVtpICsgMV07XG4gIHJldHVybiBbYSwgYl07XG59XG5cbnZhciBuYXR1cmFsID0gZnVuY3Rpb24oY29udGV4dCkge1xuICByZXR1cm4gbmV3IE5hdHVyYWwoY29udGV4dCk7XG59O1xuXG5mdW5jdGlvbiBTdGVwKGNvbnRleHQsIHQpIHtcbiAgdGhpcy5fY29udGV4dCA9IGNvbnRleHQ7XG4gIHRoaXMuX3QgPSB0O1xufVxuXG5TdGVwLnByb3RvdHlwZSA9IHtcbiAgYXJlYVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9saW5lID0gMDtcbiAgfSxcbiAgYXJlYUVuZDogZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5fbGluZSA9IE5hTjtcbiAgfSxcbiAgbGluZVN0YXJ0OiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl94ID0gdGhpcy5feSA9IE5hTjtcbiAgICB0aGlzLl9wb2ludCA9IDA7XG4gIH0sXG4gIGxpbmVFbmQ6IGZ1bmN0aW9uKCkge1xuICAgIGlmICgwIDwgdGhpcy5fdCAmJiB0aGlzLl90IDwgMSAmJiB0aGlzLl9wb2ludCA9PT0gMikgdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feCwgdGhpcy5feSk7XG4gICAgaWYgKHRoaXMuX2xpbmUgfHwgKHRoaXMuX2xpbmUgIT09IDAgJiYgdGhpcy5fcG9pbnQgPT09IDEpKSB0aGlzLl9jb250ZXh0LmNsb3NlUGF0aCgpO1xuICAgIGlmICh0aGlzLl9saW5lID49IDApIHRoaXMuX3QgPSAxIC0gdGhpcy5fdCwgdGhpcy5fbGluZSA9IDEgLSB0aGlzLl9saW5lO1xuICB9LFxuICBwb2ludDogZnVuY3Rpb24oeCwgeSkge1xuICAgIHggPSAreCwgeSA9ICt5O1xuICAgIHN3aXRjaCAodGhpcy5fcG9pbnQpIHtcbiAgICAgIGNhc2UgMDogdGhpcy5fcG9pbnQgPSAxOyB0aGlzLl9saW5lID8gdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSkgOiB0aGlzLl9jb250ZXh0Lm1vdmVUbyh4LCB5KTsgYnJlYWs7XG4gICAgICBjYXNlIDE6IHRoaXMuX3BvaW50ID0gMjsgLy8gcHJvY2VlZFxuICAgICAgZGVmYXVsdDoge1xuICAgICAgICBpZiAodGhpcy5fdCA8PSAwKSB7XG4gICAgICAgICAgdGhpcy5fY29udGV4dC5saW5lVG8odGhpcy5feCwgeSk7XG4gICAgICAgICAgdGhpcy5fY29udGV4dC5saW5lVG8oeCwgeSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdmFyIHgxID0gdGhpcy5feCAqICgxIC0gdGhpcy5fdCkgKyB4ICogdGhpcy5fdDtcbiAgICAgICAgICB0aGlzLl9jb250ZXh0LmxpbmVUbyh4MSwgdGhpcy5feSk7XG4gICAgICAgICAgdGhpcy5fY29udGV4dC5saW5lVG8oeDEsIHkpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICB0aGlzLl94ID0geCwgdGhpcy5feSA9IHk7XG4gIH1cbn07XG5cbnZhciBzdGVwID0gZnVuY3Rpb24oY29udGV4dCkge1xuICByZXR1cm4gbmV3IFN0ZXAoY29udGV4dCwgMC41KTtcbn07XG5cbmZ1bmN0aW9uIHN0ZXBCZWZvcmUoY29udGV4dCkge1xuICByZXR1cm4gbmV3IFN0ZXAoY29udGV4dCwgMCk7XG59XG5cbmZ1bmN0aW9uIHN0ZXBBZnRlcihjb250ZXh0KSB7XG4gIHJldHVybiBuZXcgU3RlcChjb250ZXh0LCAxKTtcbn1cblxudmFyIG5vbmUgPSBmdW5jdGlvbihzZXJpZXMsIG9yZGVyKSB7XG4gIGlmICghKChuID0gc2VyaWVzLmxlbmd0aCkgPiAxKSkgcmV0dXJuO1xuICBmb3IgKHZhciBpID0gMSwgaiwgczAsIHMxID0gc2VyaWVzW29yZGVyWzBdXSwgbiwgbSA9IHMxLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgIHMwID0gczEsIHMxID0gc2VyaWVzW29yZGVyW2ldXTtcbiAgICBmb3IgKGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgICBzMVtqXVsxXSArPSBzMVtqXVswXSA9IGlzTmFOKHMwW2pdWzFdKSA/IHMwW2pdWzBdIDogczBbal1bMV07XG4gICAgfVxuICB9XG59O1xuXG52YXIgbm9uZSQxID0gZnVuY3Rpb24oc2VyaWVzKSB7XG4gIHZhciBuID0gc2VyaWVzLmxlbmd0aCwgbyA9IG5ldyBBcnJheShuKTtcbiAgd2hpbGUgKC0tbiA+PSAwKSBvW25dID0gbjtcbiAgcmV0dXJuIG87XG59O1xuXG5mdW5jdGlvbiBzdGFja1ZhbHVlKGQsIGtleSkge1xuICByZXR1cm4gZFtrZXldO1xufVxuXG52YXIgc3RhY2sgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGtleXMgPSBjb25zdGFudChbXSksXG4gICAgICBvcmRlciA9IG5vbmUkMSxcbiAgICAgIG9mZnNldCA9IG5vbmUsXG4gICAgICB2YWx1ZSA9IHN0YWNrVmFsdWU7XG5cbiAgZnVuY3Rpb24gc3RhY2soZGF0YSkge1xuICAgIHZhciBreiA9IGtleXMuYXBwbHkodGhpcywgYXJndW1lbnRzKSxcbiAgICAgICAgaSxcbiAgICAgICAgbSA9IGRhdGEubGVuZ3RoLFxuICAgICAgICBuID0ga3oubGVuZ3RoLFxuICAgICAgICBzeiA9IG5ldyBBcnJheShuKSxcbiAgICAgICAgb3o7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBmb3IgKHZhciBraSA9IGt6W2ldLCBzaSA9IHN6W2ldID0gbmV3IEFycmF5KG0pLCBqID0gMCwgc2lqOyBqIDwgbTsgKytqKSB7XG4gICAgICAgIHNpW2pdID0gc2lqID0gWzAsICt2YWx1ZShkYXRhW2pdLCBraSwgaiwgZGF0YSldO1xuICAgICAgICBzaWouZGF0YSA9IGRhdGFbal07XG4gICAgICB9XG4gICAgICBzaS5rZXkgPSBraTtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwLCBveiA9IG9yZGVyKHN6KTsgaSA8IG47ICsraSkge1xuICAgICAgc3pbb3pbaV1dLmluZGV4ID0gaTtcbiAgICB9XG5cbiAgICBvZmZzZXQoc3osIG96KTtcbiAgICByZXR1cm4gc3o7XG4gIH1cblxuICBzdGFjay5rZXlzID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGtleXMgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KHNsaWNlLmNhbGwoXykpLCBzdGFjaykgOiBrZXlzO1xuICB9O1xuXG4gIHN0YWNrLnZhbHVlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHZhbHVlID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIHN0YWNrKSA6IHZhbHVlO1xuICB9O1xuXG4gIHN0YWNrLm9yZGVyID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9yZGVyID0gXyA9PSBudWxsID8gbm9uZSQxIDogdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudChzbGljZS5jYWxsKF8pKSwgc3RhY2spIDogb3JkZXI7XG4gIH07XG5cbiAgc3RhY2sub2Zmc2V0ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKG9mZnNldCA9IF8gPT0gbnVsbCA/IG5vbmUgOiBfLCBzdGFjaykgOiBvZmZzZXQ7XG4gIH07XG5cbiAgcmV0dXJuIHN0YWNrO1xufTtcblxudmFyIGV4cGFuZCA9IGZ1bmN0aW9uKHNlcmllcywgb3JkZXIpIHtcbiAgaWYgKCEoKG4gPSBzZXJpZXMubGVuZ3RoKSA+IDApKSByZXR1cm47XG4gIGZvciAodmFyIGksIG4sIGogPSAwLCBtID0gc2VyaWVzWzBdLmxlbmd0aCwgeTsgaiA8IG07ICsraikge1xuICAgIGZvciAoeSA9IGkgPSAwOyBpIDwgbjsgKytpKSB5ICs9IHNlcmllc1tpXVtqXVsxXSB8fCAwO1xuICAgIGlmICh5KSBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSBzZXJpZXNbaV1bal1bMV0gLz0geTtcbiAgfVxuICBub25lKHNlcmllcywgb3JkZXIpO1xufTtcblxudmFyIGRpdmVyZ2luZyA9IGZ1bmN0aW9uKHNlcmllcywgb3JkZXIpIHtcbiAgaWYgKCEoKG4gPSBzZXJpZXMubGVuZ3RoKSA+IDEpKSByZXR1cm47XG4gIGZvciAodmFyIGksIGogPSAwLCBkLCBkeSwgeXAsIHluLCBuLCBtID0gc2VyaWVzW29yZGVyWzBdXS5sZW5ndGg7IGogPCBtOyArK2opIHtcbiAgICBmb3IgKHlwID0geW4gPSAwLCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgaWYgKChkeSA9IChkID0gc2VyaWVzW29yZGVyW2ldXVtqXSlbMV0gLSBkWzBdKSA+PSAwKSB7XG4gICAgICAgIGRbMF0gPSB5cCwgZFsxXSA9IHlwICs9IGR5O1xuICAgICAgfSBlbHNlIGlmIChkeSA8IDApIHtcbiAgICAgICAgZFsxXSA9IHluLCBkWzBdID0geW4gKz0gZHk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkWzBdID0geXA7XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG52YXIgc2lsaG91ZXR0ZSA9IGZ1bmN0aW9uKHNlcmllcywgb3JkZXIpIHtcbiAgaWYgKCEoKG4gPSBzZXJpZXMubGVuZ3RoKSA+IDApKSByZXR1cm47XG4gIGZvciAodmFyIGogPSAwLCBzMCA9IHNlcmllc1tvcmRlclswXV0sIG4sIG0gPSBzMC5sZW5ndGg7IGogPCBtOyArK2opIHtcbiAgICBmb3IgKHZhciBpID0gMCwgeSA9IDA7IGkgPCBuOyArK2kpIHkgKz0gc2VyaWVzW2ldW2pdWzFdIHx8IDA7XG4gICAgczBbal1bMV0gKz0gczBbal1bMF0gPSAteSAvIDI7XG4gIH1cbiAgbm9uZShzZXJpZXMsIG9yZGVyKTtcbn07XG5cbnZhciB3aWdnbGUgPSBmdW5jdGlvbihzZXJpZXMsIG9yZGVyKSB7XG4gIGlmICghKChuID0gc2VyaWVzLmxlbmd0aCkgPiAwKSB8fCAhKChtID0gKHMwID0gc2VyaWVzW29yZGVyWzBdXSkubGVuZ3RoKSA+IDApKSByZXR1cm47XG4gIGZvciAodmFyIHkgPSAwLCBqID0gMSwgczAsIG0sIG47IGogPCBtOyArK2opIHtcbiAgICBmb3IgKHZhciBpID0gMCwgczEgPSAwLCBzMiA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHZhciBzaSA9IHNlcmllc1tvcmRlcltpXV0sXG4gICAgICAgICAgc2lqMCA9IHNpW2pdWzFdIHx8IDAsXG4gICAgICAgICAgc2lqMSA9IHNpW2ogLSAxXVsxXSB8fCAwLFxuICAgICAgICAgIHMzID0gKHNpajAgLSBzaWoxKSAvIDI7XG4gICAgICBmb3IgKHZhciBrID0gMDsgayA8IGk7ICsraykge1xuICAgICAgICB2YXIgc2sgPSBzZXJpZXNbb3JkZXJba11dLFxuICAgICAgICAgICAgc2tqMCA9IHNrW2pdWzFdIHx8IDAsXG4gICAgICAgICAgICBza2oxID0gc2tbaiAtIDFdWzFdIHx8IDA7XG4gICAgICAgIHMzICs9IHNrajAgLSBza2oxO1xuICAgICAgfVxuICAgICAgczEgKz0gc2lqMCwgczIgKz0gczMgKiBzaWowO1xuICAgIH1cbiAgICBzMFtqIC0gMV1bMV0gKz0gczBbaiAtIDFdWzBdID0geTtcbiAgICBpZiAoczEpIHkgLT0gczIgLyBzMTtcbiAgfVxuICBzMFtqIC0gMV1bMV0gKz0gczBbaiAtIDFdWzBdID0geTtcbiAgbm9uZShzZXJpZXMsIG9yZGVyKTtcbn07XG5cbnZhciBhc2NlbmRpbmcgPSBmdW5jdGlvbihzZXJpZXMpIHtcbiAgdmFyIHN1bXMgPSBzZXJpZXMubWFwKHN1bSk7XG4gIHJldHVybiBub25lJDEoc2VyaWVzKS5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIHN1bXNbYV0gLSBzdW1zW2JdOyB9KTtcbn07XG5cbmZ1bmN0aW9uIHN1bShzZXJpZXMpIHtcbiAgdmFyIHMgPSAwLCBpID0gLTEsIG4gPSBzZXJpZXMubGVuZ3RoLCB2O1xuICB3aGlsZSAoKytpIDwgbikgaWYgKHYgPSArc2VyaWVzW2ldWzFdKSBzICs9IHY7XG4gIHJldHVybiBzO1xufVxuXG52YXIgZGVzY2VuZGluZyQxID0gZnVuY3Rpb24oc2VyaWVzKSB7XG4gIHJldHVybiBhc2NlbmRpbmcoc2VyaWVzKS5yZXZlcnNlKCk7XG59O1xuXG52YXIgaW5zaWRlT3V0ID0gZnVuY3Rpb24oc2VyaWVzKSB7XG4gIHZhciBuID0gc2VyaWVzLmxlbmd0aCxcbiAgICAgIGksXG4gICAgICBqLFxuICAgICAgc3VtcyA9IHNlcmllcy5tYXAoc3VtKSxcbiAgICAgIG9yZGVyID0gbm9uZSQxKHNlcmllcykuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBzdW1zW2JdIC0gc3Vtc1thXTsgfSksXG4gICAgICB0b3AgPSAwLFxuICAgICAgYm90dG9tID0gMCxcbiAgICAgIHRvcHMgPSBbXSxcbiAgICAgIGJvdHRvbXMgPSBbXTtcblxuICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgaiA9IG9yZGVyW2ldO1xuICAgIGlmICh0b3AgPCBib3R0b20pIHtcbiAgICAgIHRvcCArPSBzdW1zW2pdO1xuICAgICAgdG9wcy5wdXNoKGopO1xuICAgIH0gZWxzZSB7XG4gICAgICBib3R0b20gKz0gc3Vtc1tqXTtcbiAgICAgIGJvdHRvbXMucHVzaChqKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYm90dG9tcy5yZXZlcnNlKCkuY29uY2F0KHRvcHMpO1xufTtcblxudmFyIHJldmVyc2UgPSBmdW5jdGlvbihzZXJpZXMpIHtcbiAgcmV0dXJuIG5vbmUkMShzZXJpZXMpLnJldmVyc2UoKTtcbn07XG5cbmV4cG9ydHMuYXJjID0gYXJjO1xuZXhwb3J0cy5hcmVhID0gYXJlYTtcbmV4cG9ydHMubGluZSA9IGxpbmU7XG5leHBvcnRzLnBpZSA9IHBpZTtcbmV4cG9ydHMuYXJlYVJhZGlhbCA9IGFyZWFSYWRpYWw7XG5leHBvcnRzLnJhZGlhbEFyZWEgPSBhcmVhUmFkaWFsO1xuZXhwb3J0cy5saW5lUmFkaWFsID0gbGluZVJhZGlhbCQxO1xuZXhwb3J0cy5yYWRpYWxMaW5lID0gbGluZVJhZGlhbCQxO1xuZXhwb3J0cy5wb2ludFJhZGlhbCA9IHBvaW50UmFkaWFsO1xuZXhwb3J0cy5saW5rSG9yaXpvbnRhbCA9IGxpbmtIb3Jpem9udGFsO1xuZXhwb3J0cy5saW5rVmVydGljYWwgPSBsaW5rVmVydGljYWw7XG5leHBvcnRzLmxpbmtSYWRpYWwgPSBsaW5rUmFkaWFsO1xuZXhwb3J0cy5zeW1ib2wgPSBzeW1ib2w7XG5leHBvcnRzLnN5bWJvbHMgPSBzeW1ib2xzO1xuZXhwb3J0cy5zeW1ib2xDaXJjbGUgPSBjaXJjbGU7XG5leHBvcnRzLnN5bWJvbENyb3NzID0gY3Jvc3M7XG5leHBvcnRzLnN5bWJvbERpYW1vbmQgPSBkaWFtb25kO1xuZXhwb3J0cy5zeW1ib2xTcXVhcmUgPSBzcXVhcmU7XG5leHBvcnRzLnN5bWJvbFN0YXIgPSBzdGFyO1xuZXhwb3J0cy5zeW1ib2xUcmlhbmdsZSA9IHRyaWFuZ2xlO1xuZXhwb3J0cy5zeW1ib2xXeWUgPSB3eWU7XG5leHBvcnRzLmN1cnZlQmFzaXNDbG9zZWQgPSBiYXNpc0Nsb3NlZDtcbmV4cG9ydHMuY3VydmVCYXNpc09wZW4gPSBiYXNpc09wZW47XG5leHBvcnRzLmN1cnZlQmFzaXMgPSBiYXNpcztcbmV4cG9ydHMuY3VydmVCdW5kbGUgPSBidW5kbGU7XG5leHBvcnRzLmN1cnZlQ2FyZGluYWxDbG9zZWQgPSBjYXJkaW5hbENsb3NlZDtcbmV4cG9ydHMuY3VydmVDYXJkaW5hbE9wZW4gPSBjYXJkaW5hbE9wZW47XG5leHBvcnRzLmN1cnZlQ2FyZGluYWwgPSBjYXJkaW5hbDtcbmV4cG9ydHMuY3VydmVDYXRtdWxsUm9tQ2xvc2VkID0gY2F0bXVsbFJvbUNsb3NlZDtcbmV4cG9ydHMuY3VydmVDYXRtdWxsUm9tT3BlbiA9IGNhdG11bGxSb21PcGVuO1xuZXhwb3J0cy5jdXJ2ZUNhdG11bGxSb20gPSBjYXRtdWxsUm9tO1xuZXhwb3J0cy5jdXJ2ZUxpbmVhckNsb3NlZCA9IGxpbmVhckNsb3NlZDtcbmV4cG9ydHMuY3VydmVMaW5lYXIgPSBjdXJ2ZUxpbmVhcjtcbmV4cG9ydHMuY3VydmVNb25vdG9uZVggPSBtb25vdG9uZVg7XG5leHBvcnRzLmN1cnZlTW9ub3RvbmVZID0gbW9ub3RvbmVZO1xuZXhwb3J0cy5jdXJ2ZU5hdHVyYWwgPSBuYXR1cmFsO1xuZXhwb3J0cy5jdXJ2ZVN0ZXAgPSBzdGVwO1xuZXhwb3J0cy5jdXJ2ZVN0ZXBBZnRlciA9IHN0ZXBBZnRlcjtcbmV4cG9ydHMuY3VydmVTdGVwQmVmb3JlID0gc3RlcEJlZm9yZTtcbmV4cG9ydHMuc3RhY2sgPSBzdGFjaztcbmV4cG9ydHMuc3RhY2tPZmZzZXRFeHBhbmQgPSBleHBhbmQ7XG5leHBvcnRzLnN0YWNrT2Zmc2V0RGl2ZXJnaW5nID0gZGl2ZXJnaW5nO1xuZXhwb3J0cy5zdGFja09mZnNldE5vbmUgPSBub25lO1xuZXhwb3J0cy5zdGFja09mZnNldFNpbGhvdWV0dGUgPSBzaWxob3VldHRlO1xuZXhwb3J0cy5zdGFja09mZnNldFdpZ2dsZSA9IHdpZ2dsZTtcbmV4cG9ydHMuc3RhY2tPcmRlckFzY2VuZGluZyA9IGFzY2VuZGluZztcbmV4cG9ydHMuc3RhY2tPcmRlckRlc2NlbmRpbmcgPSBkZXNjZW5kaW5nJDE7XG5leHBvcnRzLnN0YWNrT3JkZXJJbnNpZGVPdXQgPSBpbnNpZGVPdXQ7XG5leHBvcnRzLnN0YWNrT3JkZXJOb25lID0gbm9uZSQxO1xuZXhwb3J0cy5zdGFja09yZGVyUmV2ZXJzZSA9IHJldmVyc2U7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLXRpbWUtZm9ybWF0LyBWZXJzaW9uIDIuMS4xLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIHJlcXVpcmUoJ2QzLXRpbWUnKSkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ2QzLXRpbWUnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLGQzVGltZSkgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIGxvY2FsRGF0ZShkKSB7XG4gIGlmICgwIDw9IGQueSAmJiBkLnkgPCAxMDApIHtcbiAgICB2YXIgZGF0ZSA9IG5ldyBEYXRlKC0xLCBkLm0sIGQuZCwgZC5ILCBkLk0sIGQuUywgZC5MKTtcbiAgICBkYXRlLnNldEZ1bGxZZWFyKGQueSk7XG4gICAgcmV0dXJuIGRhdGU7XG4gIH1cbiAgcmV0dXJuIG5ldyBEYXRlKGQueSwgZC5tLCBkLmQsIGQuSCwgZC5NLCBkLlMsIGQuTCk7XG59XG5cbmZ1bmN0aW9uIHV0Y0RhdGUoZCkge1xuICBpZiAoMCA8PSBkLnkgJiYgZC55IDwgMTAwKSB7XG4gICAgdmFyIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQygtMSwgZC5tLCBkLmQsIGQuSCwgZC5NLCBkLlMsIGQuTCkpO1xuICAgIGRhdGUuc2V0VVRDRnVsbFllYXIoZC55KTtcbiAgICByZXR1cm4gZGF0ZTtcbiAgfVxuICByZXR1cm4gbmV3IERhdGUoRGF0ZS5VVEMoZC55LCBkLm0sIGQuZCwgZC5ILCBkLk0sIGQuUywgZC5MKSk7XG59XG5cbmZ1bmN0aW9uIG5ld1llYXIoeSkge1xuICByZXR1cm4ge3k6IHksIG06IDAsIGQ6IDEsIEg6IDAsIE06IDAsIFM6IDAsIEw6IDB9O1xufVxuXG5mdW5jdGlvbiBmb3JtYXRMb2NhbGUobG9jYWxlKSB7XG4gIHZhciBsb2NhbGVfZGF0ZVRpbWUgPSBsb2NhbGUuZGF0ZVRpbWUsXG4gICAgICBsb2NhbGVfZGF0ZSA9IGxvY2FsZS5kYXRlLFxuICAgICAgbG9jYWxlX3RpbWUgPSBsb2NhbGUudGltZSxcbiAgICAgIGxvY2FsZV9wZXJpb2RzID0gbG9jYWxlLnBlcmlvZHMsXG4gICAgICBsb2NhbGVfd2Vla2RheXMgPSBsb2NhbGUuZGF5cyxcbiAgICAgIGxvY2FsZV9zaG9ydFdlZWtkYXlzID0gbG9jYWxlLnNob3J0RGF5cyxcbiAgICAgIGxvY2FsZV9tb250aHMgPSBsb2NhbGUubW9udGhzLFxuICAgICAgbG9jYWxlX3Nob3J0TW9udGhzID0gbG9jYWxlLnNob3J0TW9udGhzO1xuXG4gIHZhciBwZXJpb2RSZSA9IGZvcm1hdFJlKGxvY2FsZV9wZXJpb2RzKSxcbiAgICAgIHBlcmlvZExvb2t1cCA9IGZvcm1hdExvb2t1cChsb2NhbGVfcGVyaW9kcyksXG4gICAgICB3ZWVrZGF5UmUgPSBmb3JtYXRSZShsb2NhbGVfd2Vla2RheXMpLFxuICAgICAgd2Vla2RheUxvb2t1cCA9IGZvcm1hdExvb2t1cChsb2NhbGVfd2Vla2RheXMpLFxuICAgICAgc2hvcnRXZWVrZGF5UmUgPSBmb3JtYXRSZShsb2NhbGVfc2hvcnRXZWVrZGF5cyksXG4gICAgICBzaG9ydFdlZWtkYXlMb29rdXAgPSBmb3JtYXRMb29rdXAobG9jYWxlX3Nob3J0V2Vla2RheXMpLFxuICAgICAgbW9udGhSZSA9IGZvcm1hdFJlKGxvY2FsZV9tb250aHMpLFxuICAgICAgbW9udGhMb29rdXAgPSBmb3JtYXRMb29rdXAobG9jYWxlX21vbnRocyksXG4gICAgICBzaG9ydE1vbnRoUmUgPSBmb3JtYXRSZShsb2NhbGVfc2hvcnRNb250aHMpLFxuICAgICAgc2hvcnRNb250aExvb2t1cCA9IGZvcm1hdExvb2t1cChsb2NhbGVfc2hvcnRNb250aHMpO1xuXG4gIHZhciBmb3JtYXRzID0ge1xuICAgIFwiYVwiOiBmb3JtYXRTaG9ydFdlZWtkYXksXG4gICAgXCJBXCI6IGZvcm1hdFdlZWtkYXksXG4gICAgXCJiXCI6IGZvcm1hdFNob3J0TW9udGgsXG4gICAgXCJCXCI6IGZvcm1hdE1vbnRoLFxuICAgIFwiY1wiOiBudWxsLFxuICAgIFwiZFwiOiBmb3JtYXREYXlPZk1vbnRoLFxuICAgIFwiZVwiOiBmb3JtYXREYXlPZk1vbnRoLFxuICAgIFwiZlwiOiBmb3JtYXRNaWNyb3NlY29uZHMsXG4gICAgXCJIXCI6IGZvcm1hdEhvdXIyNCxcbiAgICBcIklcIjogZm9ybWF0SG91cjEyLFxuICAgIFwialwiOiBmb3JtYXREYXlPZlllYXIsXG4gICAgXCJMXCI6IGZvcm1hdE1pbGxpc2Vjb25kcyxcbiAgICBcIm1cIjogZm9ybWF0TW9udGhOdW1iZXIsXG4gICAgXCJNXCI6IGZvcm1hdE1pbnV0ZXMsXG4gICAgXCJwXCI6IGZvcm1hdFBlcmlvZCxcbiAgICBcIlFcIjogZm9ybWF0VW5peFRpbWVzdGFtcCxcbiAgICBcInNcIjogZm9ybWF0VW5peFRpbWVzdGFtcFNlY29uZHMsXG4gICAgXCJTXCI6IGZvcm1hdFNlY29uZHMsXG4gICAgXCJ1XCI6IGZvcm1hdFdlZWtkYXlOdW1iZXJNb25kYXksXG4gICAgXCJVXCI6IGZvcm1hdFdlZWtOdW1iZXJTdW5kYXksXG4gICAgXCJWXCI6IGZvcm1hdFdlZWtOdW1iZXJJU08sXG4gICAgXCJ3XCI6IGZvcm1hdFdlZWtkYXlOdW1iZXJTdW5kYXksXG4gICAgXCJXXCI6IGZvcm1hdFdlZWtOdW1iZXJNb25kYXksXG4gICAgXCJ4XCI6IG51bGwsXG4gICAgXCJYXCI6IG51bGwsXG4gICAgXCJ5XCI6IGZvcm1hdFllYXIsXG4gICAgXCJZXCI6IGZvcm1hdEZ1bGxZZWFyLFxuICAgIFwiWlwiOiBmb3JtYXRab25lLFxuICAgIFwiJVwiOiBmb3JtYXRMaXRlcmFsUGVyY2VudFxuICB9O1xuXG4gIHZhciB1dGNGb3JtYXRzID0ge1xuICAgIFwiYVwiOiBmb3JtYXRVVENTaG9ydFdlZWtkYXksXG4gICAgXCJBXCI6IGZvcm1hdFVUQ1dlZWtkYXksXG4gICAgXCJiXCI6IGZvcm1hdFVUQ1Nob3J0TW9udGgsXG4gICAgXCJCXCI6IGZvcm1hdFVUQ01vbnRoLFxuICAgIFwiY1wiOiBudWxsLFxuICAgIFwiZFwiOiBmb3JtYXRVVENEYXlPZk1vbnRoLFxuICAgIFwiZVwiOiBmb3JtYXRVVENEYXlPZk1vbnRoLFxuICAgIFwiZlwiOiBmb3JtYXRVVENNaWNyb3NlY29uZHMsXG4gICAgXCJIXCI6IGZvcm1hdFVUQ0hvdXIyNCxcbiAgICBcIklcIjogZm9ybWF0VVRDSG91cjEyLFxuICAgIFwialwiOiBmb3JtYXRVVENEYXlPZlllYXIsXG4gICAgXCJMXCI6IGZvcm1hdFVUQ01pbGxpc2Vjb25kcyxcbiAgICBcIm1cIjogZm9ybWF0VVRDTW9udGhOdW1iZXIsXG4gICAgXCJNXCI6IGZvcm1hdFVUQ01pbnV0ZXMsXG4gICAgXCJwXCI6IGZvcm1hdFVUQ1BlcmlvZCxcbiAgICBcIlFcIjogZm9ybWF0VW5peFRpbWVzdGFtcCxcbiAgICBcInNcIjogZm9ybWF0VW5peFRpbWVzdGFtcFNlY29uZHMsXG4gICAgXCJTXCI6IGZvcm1hdFVUQ1NlY29uZHMsXG4gICAgXCJ1XCI6IGZvcm1hdFVUQ1dlZWtkYXlOdW1iZXJNb25kYXksXG4gICAgXCJVXCI6IGZvcm1hdFVUQ1dlZWtOdW1iZXJTdW5kYXksXG4gICAgXCJWXCI6IGZvcm1hdFVUQ1dlZWtOdW1iZXJJU08sXG4gICAgXCJ3XCI6IGZvcm1hdFVUQ1dlZWtkYXlOdW1iZXJTdW5kYXksXG4gICAgXCJXXCI6IGZvcm1hdFVUQ1dlZWtOdW1iZXJNb25kYXksXG4gICAgXCJ4XCI6IG51bGwsXG4gICAgXCJYXCI6IG51bGwsXG4gICAgXCJ5XCI6IGZvcm1hdFVUQ1llYXIsXG4gICAgXCJZXCI6IGZvcm1hdFVUQ0Z1bGxZZWFyLFxuICAgIFwiWlwiOiBmb3JtYXRVVENab25lLFxuICAgIFwiJVwiOiBmb3JtYXRMaXRlcmFsUGVyY2VudFxuICB9O1xuXG4gIHZhciBwYXJzZXMgPSB7XG4gICAgXCJhXCI6IHBhcnNlU2hvcnRXZWVrZGF5LFxuICAgIFwiQVwiOiBwYXJzZVdlZWtkYXksXG4gICAgXCJiXCI6IHBhcnNlU2hvcnRNb250aCxcbiAgICBcIkJcIjogcGFyc2VNb250aCxcbiAgICBcImNcIjogcGFyc2VMb2NhbGVEYXRlVGltZSxcbiAgICBcImRcIjogcGFyc2VEYXlPZk1vbnRoLFxuICAgIFwiZVwiOiBwYXJzZURheU9mTW9udGgsXG4gICAgXCJmXCI6IHBhcnNlTWljcm9zZWNvbmRzLFxuICAgIFwiSFwiOiBwYXJzZUhvdXIyNCxcbiAgICBcIklcIjogcGFyc2VIb3VyMjQsXG4gICAgXCJqXCI6IHBhcnNlRGF5T2ZZZWFyLFxuICAgIFwiTFwiOiBwYXJzZU1pbGxpc2Vjb25kcyxcbiAgICBcIm1cIjogcGFyc2VNb250aE51bWJlcixcbiAgICBcIk1cIjogcGFyc2VNaW51dGVzLFxuICAgIFwicFwiOiBwYXJzZVBlcmlvZCxcbiAgICBcIlFcIjogcGFyc2VVbml4VGltZXN0YW1wLFxuICAgIFwic1wiOiBwYXJzZVVuaXhUaW1lc3RhbXBTZWNvbmRzLFxuICAgIFwiU1wiOiBwYXJzZVNlY29uZHMsXG4gICAgXCJ1XCI6IHBhcnNlV2Vla2RheU51bWJlck1vbmRheSxcbiAgICBcIlVcIjogcGFyc2VXZWVrTnVtYmVyU3VuZGF5LFxuICAgIFwiVlwiOiBwYXJzZVdlZWtOdW1iZXJJU08sXG4gICAgXCJ3XCI6IHBhcnNlV2Vla2RheU51bWJlclN1bmRheSxcbiAgICBcIldcIjogcGFyc2VXZWVrTnVtYmVyTW9uZGF5LFxuICAgIFwieFwiOiBwYXJzZUxvY2FsZURhdGUsXG4gICAgXCJYXCI6IHBhcnNlTG9jYWxlVGltZSxcbiAgICBcInlcIjogcGFyc2VZZWFyLFxuICAgIFwiWVwiOiBwYXJzZUZ1bGxZZWFyLFxuICAgIFwiWlwiOiBwYXJzZVpvbmUsXG4gICAgXCIlXCI6IHBhcnNlTGl0ZXJhbFBlcmNlbnRcbiAgfTtcblxuICAvLyBUaGVzZSByZWN1cnNpdmUgZGlyZWN0aXZlIGRlZmluaXRpb25zIG11c3QgYmUgZGVmZXJyZWQuXG4gIGZvcm1hdHMueCA9IG5ld0Zvcm1hdChsb2NhbGVfZGF0ZSwgZm9ybWF0cyk7XG4gIGZvcm1hdHMuWCA9IG5ld0Zvcm1hdChsb2NhbGVfdGltZSwgZm9ybWF0cyk7XG4gIGZvcm1hdHMuYyA9IG5ld0Zvcm1hdChsb2NhbGVfZGF0ZVRpbWUsIGZvcm1hdHMpO1xuICB1dGNGb3JtYXRzLnggPSBuZXdGb3JtYXQobG9jYWxlX2RhdGUsIHV0Y0Zvcm1hdHMpO1xuICB1dGNGb3JtYXRzLlggPSBuZXdGb3JtYXQobG9jYWxlX3RpbWUsIHV0Y0Zvcm1hdHMpO1xuICB1dGNGb3JtYXRzLmMgPSBuZXdGb3JtYXQobG9jYWxlX2RhdGVUaW1lLCB1dGNGb3JtYXRzKTtcblxuICBmdW5jdGlvbiBuZXdGb3JtYXQoc3BlY2lmaWVyLCBmb3JtYXRzKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGRhdGUpIHtcbiAgICAgIHZhciBzdHJpbmcgPSBbXSxcbiAgICAgICAgICBpID0gLTEsXG4gICAgICAgICAgaiA9IDAsXG4gICAgICAgICAgbiA9IHNwZWNpZmllci5sZW5ndGgsXG4gICAgICAgICAgYyxcbiAgICAgICAgICBwYWQsXG4gICAgICAgICAgZm9ybWF0O1xuXG4gICAgICBpZiAoIShkYXRlIGluc3RhbmNlb2YgRGF0ZSkpIGRhdGUgPSBuZXcgRGF0ZSgrZGF0ZSk7XG5cbiAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgIGlmIChzcGVjaWZpZXIuY2hhckNvZGVBdChpKSA9PT0gMzcpIHtcbiAgICAgICAgICBzdHJpbmcucHVzaChzcGVjaWZpZXIuc2xpY2UoaiwgaSkpO1xuICAgICAgICAgIGlmICgocGFkID0gcGFkc1tjID0gc3BlY2lmaWVyLmNoYXJBdCgrK2kpXSkgIT0gbnVsbCkgYyA9IHNwZWNpZmllci5jaGFyQXQoKytpKTtcbiAgICAgICAgICBlbHNlIHBhZCA9IGMgPT09IFwiZVwiID8gXCIgXCIgOiBcIjBcIjtcbiAgICAgICAgICBpZiAoZm9ybWF0ID0gZm9ybWF0c1tjXSkgYyA9IGZvcm1hdChkYXRlLCBwYWQpO1xuICAgICAgICAgIHN0cmluZy5wdXNoKGMpO1xuICAgICAgICAgIGogPSBpICsgMTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBzdHJpbmcucHVzaChzcGVjaWZpZXIuc2xpY2UoaiwgaSkpO1xuICAgICAgcmV0dXJuIHN0cmluZy5qb2luKFwiXCIpO1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBuZXdQYXJzZShzcGVjaWZpZXIsIG5ld0RhdGUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICB2YXIgZCA9IG5ld1llYXIoMTkwMCksXG4gICAgICAgICAgaSA9IHBhcnNlU3BlY2lmaWVyKGQsIHNwZWNpZmllciwgc3RyaW5nICs9IFwiXCIsIDApLFxuICAgICAgICAgIHdlZWssIGRheTtcbiAgICAgIGlmIChpICE9IHN0cmluZy5sZW5ndGgpIHJldHVybiBudWxsO1xuXG4gICAgICAvLyBJZiBhIFVOSVggdGltZXN0YW1wIGlzIHNwZWNpZmllZCwgcmV0dXJuIGl0LlxuICAgICAgaWYgKFwiUVwiIGluIGQpIHJldHVybiBuZXcgRGF0ZShkLlEpO1xuXG4gICAgICAvLyBUaGUgYW0tcG0gZmxhZyBpcyAwIGZvciBBTSwgYW5kIDEgZm9yIFBNLlxuICAgICAgaWYgKFwicFwiIGluIGQpIGQuSCA9IGQuSCAlIDEyICsgZC5wICogMTI7XG5cbiAgICAgIC8vIENvbnZlcnQgZGF5LW9mLXdlZWsgYW5kIHdlZWstb2YteWVhciB0byBkYXktb2YteWVhci5cbiAgICAgIGlmIChcIlZcIiBpbiBkKSB7XG4gICAgICAgIGlmIChkLlYgPCAxIHx8IGQuViA+IDUzKSByZXR1cm4gbnVsbDtcbiAgICAgICAgaWYgKCEoXCJ3XCIgaW4gZCkpIGQudyA9IDE7XG4gICAgICAgIGlmIChcIlpcIiBpbiBkKSB7XG4gICAgICAgICAgd2VlayA9IHV0Y0RhdGUobmV3WWVhcihkLnkpKSwgZGF5ID0gd2Vlay5nZXRVVENEYXkoKTtcbiAgICAgICAgICB3ZWVrID0gZGF5ID4gNCB8fCBkYXkgPT09IDAgPyBkM1RpbWUudXRjTW9uZGF5LmNlaWwod2VlaykgOiBkM1RpbWUudXRjTW9uZGF5KHdlZWspO1xuICAgICAgICAgIHdlZWsgPSBkM1RpbWUudXRjRGF5Lm9mZnNldCh3ZWVrLCAoZC5WIC0gMSkgKiA3KTtcbiAgICAgICAgICBkLnkgPSB3ZWVrLmdldFVUQ0Z1bGxZZWFyKCk7XG4gICAgICAgICAgZC5tID0gd2Vlay5nZXRVVENNb250aCgpO1xuICAgICAgICAgIGQuZCA9IHdlZWsuZ2V0VVRDRGF0ZSgpICsgKGQudyArIDYpICUgNztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB3ZWVrID0gbmV3RGF0ZShuZXdZZWFyKGQueSkpLCBkYXkgPSB3ZWVrLmdldERheSgpO1xuICAgICAgICAgIHdlZWsgPSBkYXkgPiA0IHx8IGRheSA9PT0gMCA/IGQzVGltZS50aW1lTW9uZGF5LmNlaWwod2VlaykgOiBkM1RpbWUudGltZU1vbmRheSh3ZWVrKTtcbiAgICAgICAgICB3ZWVrID0gZDNUaW1lLnRpbWVEYXkub2Zmc2V0KHdlZWssIChkLlYgLSAxKSAqIDcpO1xuICAgICAgICAgIGQueSA9IHdlZWsuZ2V0RnVsbFllYXIoKTtcbiAgICAgICAgICBkLm0gPSB3ZWVrLmdldE1vbnRoKCk7XG4gICAgICAgICAgZC5kID0gd2Vlay5nZXREYXRlKCkgKyAoZC53ICsgNikgJSA3O1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKFwiV1wiIGluIGQgfHwgXCJVXCIgaW4gZCkge1xuICAgICAgICBpZiAoIShcIndcIiBpbiBkKSkgZC53ID0gXCJ1XCIgaW4gZCA/IGQudSAlIDcgOiBcIldcIiBpbiBkID8gMSA6IDA7XG4gICAgICAgIGRheSA9IFwiWlwiIGluIGQgPyB1dGNEYXRlKG5ld1llYXIoZC55KSkuZ2V0VVRDRGF5KCkgOiBuZXdEYXRlKG5ld1llYXIoZC55KSkuZ2V0RGF5KCk7XG4gICAgICAgIGQubSA9IDA7XG4gICAgICAgIGQuZCA9IFwiV1wiIGluIGQgPyAoZC53ICsgNikgJSA3ICsgZC5XICogNyAtIChkYXkgKyA1KSAlIDcgOiBkLncgKyBkLlUgKiA3IC0gKGRheSArIDYpICUgNztcbiAgICAgIH1cblxuICAgICAgLy8gSWYgYSB0aW1lIHpvbmUgaXMgc3BlY2lmaWVkLCBhbGwgZmllbGRzIGFyZSBpbnRlcnByZXRlZCBhcyBVVEMgYW5kIHRoZW5cbiAgICAgIC8vIG9mZnNldCBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCB0aW1lIHpvbmUuXG4gICAgICBpZiAoXCJaXCIgaW4gZCkge1xuICAgICAgICBkLkggKz0gZC5aIC8gMTAwIHwgMDtcbiAgICAgICAgZC5NICs9IGQuWiAlIDEwMDtcbiAgICAgICAgcmV0dXJuIHV0Y0RhdGUoZCk7XG4gICAgICB9XG5cbiAgICAgIC8vIE90aGVyd2lzZSwgYWxsIGZpZWxkcyBhcmUgaW4gbG9jYWwgdGltZS5cbiAgICAgIHJldHVybiBuZXdEYXRlKGQpO1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVNwZWNpZmllcihkLCBzcGVjaWZpZXIsIHN0cmluZywgaikge1xuICAgIHZhciBpID0gMCxcbiAgICAgICAgbiA9IHNwZWNpZmllci5sZW5ndGgsXG4gICAgICAgIG0gPSBzdHJpbmcubGVuZ3RoLFxuICAgICAgICBjLFxuICAgICAgICBwYXJzZTtcblxuICAgIHdoaWxlIChpIDwgbikge1xuICAgICAgaWYgKGogPj0gbSkgcmV0dXJuIC0xO1xuICAgICAgYyA9IHNwZWNpZmllci5jaGFyQ29kZUF0KGkrKyk7XG4gICAgICBpZiAoYyA9PT0gMzcpIHtcbiAgICAgICAgYyA9IHNwZWNpZmllci5jaGFyQXQoaSsrKTtcbiAgICAgICAgcGFyc2UgPSBwYXJzZXNbYyBpbiBwYWRzID8gc3BlY2lmaWVyLmNoYXJBdChpKyspIDogY107XG4gICAgICAgIGlmICghcGFyc2UgfHwgKChqID0gcGFyc2UoZCwgc3RyaW5nLCBqKSkgPCAwKSkgcmV0dXJuIC0xO1xuICAgICAgfSBlbHNlIGlmIChjICE9IHN0cmluZy5jaGFyQ29kZUF0KGorKykpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBqO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VQZXJpb2QoZCwgc3RyaW5nLCBpKSB7XG4gICAgdmFyIG4gPSBwZXJpb2RSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgcmV0dXJuIG4gPyAoZC5wID0gcGVyaW9kTG9va3VwW25bMF0udG9Mb3dlckNhc2UoKV0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlU2hvcnRXZWVrZGF5KGQsIHN0cmluZywgaSkge1xuICAgIHZhciBuID0gc2hvcnRXZWVrZGF5UmUuZXhlYyhzdHJpbmcuc2xpY2UoaSkpO1xuICAgIHJldHVybiBuID8gKGQudyA9IHNob3J0V2Vla2RheUxvb2t1cFtuWzBdLnRvTG93ZXJDYXNlKCldLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVdlZWtkYXkoZCwgc3RyaW5nLCBpKSB7XG4gICAgdmFyIG4gPSB3ZWVrZGF5UmUuZXhlYyhzdHJpbmcuc2xpY2UoaSkpO1xuICAgIHJldHVybiBuID8gKGQudyA9IHdlZWtkYXlMb29rdXBbblswXS50b0xvd2VyQ2FzZSgpXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VTaG9ydE1vbnRoKGQsIHN0cmluZywgaSkge1xuICAgIHZhciBuID0gc2hvcnRNb250aFJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICByZXR1cm4gbiA/IChkLm0gPSBzaG9ydE1vbnRoTG9va3VwW25bMF0udG9Mb3dlckNhc2UoKV0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlTW9udGgoZCwgc3RyaW5nLCBpKSB7XG4gICAgdmFyIG4gPSBtb250aFJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICByZXR1cm4gbiA/IChkLm0gPSBtb250aExvb2t1cFtuWzBdLnRvTG93ZXJDYXNlKCldLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUxvY2FsZURhdGVUaW1lKGQsIHN0cmluZywgaSkge1xuICAgIHJldHVybiBwYXJzZVNwZWNpZmllcihkLCBsb2NhbGVfZGF0ZVRpbWUsIHN0cmluZywgaSk7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUxvY2FsZURhdGUoZCwgc3RyaW5nLCBpKSB7XG4gICAgcmV0dXJuIHBhcnNlU3BlY2lmaWVyKGQsIGxvY2FsZV9kYXRlLCBzdHJpbmcsIGkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VMb2NhbGVUaW1lKGQsIHN0cmluZywgaSkge1xuICAgIHJldHVybiBwYXJzZVNwZWNpZmllcihkLCBsb2NhbGVfdGltZSwgc3RyaW5nLCBpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFNob3J0V2Vla2RheShkKSB7XG4gICAgcmV0dXJuIGxvY2FsZV9zaG9ydFdlZWtkYXlzW2QuZ2V0RGF5KCldO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0V2Vla2RheShkKSB7XG4gICAgcmV0dXJuIGxvY2FsZV93ZWVrZGF5c1tkLmdldERheSgpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFNob3J0TW9udGgoZCkge1xuICAgIHJldHVybiBsb2NhbGVfc2hvcnRNb250aHNbZC5nZXRNb250aCgpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdE1vbnRoKGQpIHtcbiAgICByZXR1cm4gbG9jYWxlX21vbnRoc1tkLmdldE1vbnRoKCldO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0UGVyaW9kKGQpIHtcbiAgICByZXR1cm4gbG9jYWxlX3BlcmlvZHNbKyhkLmdldEhvdXJzKCkgPj0gMTIpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ1Nob3J0V2Vla2RheShkKSB7XG4gICAgcmV0dXJuIGxvY2FsZV9zaG9ydFdlZWtkYXlzW2QuZ2V0VVRDRGF5KCldO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0VVRDV2Vla2RheShkKSB7XG4gICAgcmV0dXJuIGxvY2FsZV93ZWVrZGF5c1tkLmdldFVUQ0RheSgpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ1Nob3J0TW9udGgoZCkge1xuICAgIHJldHVybiBsb2NhbGVfc2hvcnRNb250aHNbZC5nZXRVVENNb250aCgpXTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ01vbnRoKGQpIHtcbiAgICByZXR1cm4gbG9jYWxlX21vbnRoc1tkLmdldFVUQ01vbnRoKCldO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0VVRDUGVyaW9kKGQpIHtcbiAgICByZXR1cm4gbG9jYWxlX3BlcmlvZHNbKyhkLmdldFVUQ0hvdXJzKCkgPj0gMTIpXTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZm9ybWF0OiBmdW5jdGlvbihzcGVjaWZpZXIpIHtcbiAgICAgIHZhciBmID0gbmV3Rm9ybWF0KHNwZWNpZmllciArPSBcIlwiLCBmb3JtYXRzKTtcbiAgICAgIGYudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHNwZWNpZmllcjsgfTtcbiAgICAgIHJldHVybiBmO1xuICAgIH0sXG4gICAgcGFyc2U6IGZ1bmN0aW9uKHNwZWNpZmllcikge1xuICAgICAgdmFyIHAgPSBuZXdQYXJzZShzcGVjaWZpZXIgKz0gXCJcIiwgbG9jYWxEYXRlKTtcbiAgICAgIHAudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHNwZWNpZmllcjsgfTtcbiAgICAgIHJldHVybiBwO1xuICAgIH0sXG4gICAgdXRjRm9ybWF0OiBmdW5jdGlvbihzcGVjaWZpZXIpIHtcbiAgICAgIHZhciBmID0gbmV3Rm9ybWF0KHNwZWNpZmllciArPSBcIlwiLCB1dGNGb3JtYXRzKTtcbiAgICAgIGYudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHNwZWNpZmllcjsgfTtcbiAgICAgIHJldHVybiBmO1xuICAgIH0sXG4gICAgdXRjUGFyc2U6IGZ1bmN0aW9uKHNwZWNpZmllcikge1xuICAgICAgdmFyIHAgPSBuZXdQYXJzZShzcGVjaWZpZXIsIHV0Y0RhdGUpO1xuICAgICAgcC50b1N0cmluZyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gc3BlY2lmaWVyOyB9O1xuICAgICAgcmV0dXJuIHA7XG4gICAgfVxuICB9O1xufVxuXG52YXIgcGFkcyA9IHtcIi1cIjogXCJcIiwgXCJfXCI6IFwiIFwiLCBcIjBcIjogXCIwXCJ9O1xudmFyIG51bWJlclJlID0gL15cXHMqXFxkKy87XG52YXIgcGVyY2VudFJlID0gL14lLztcbnZhciByZXF1b3RlUmUgPSAvW1xcXFxeJCorP3xbXFxdKCkue31dL2c7XG5cbmZ1bmN0aW9uIHBhZCh2YWx1ZSwgZmlsbCwgd2lkdGgpIHtcbiAgdmFyIHNpZ24gPSB2YWx1ZSA8IDAgPyBcIi1cIiA6IFwiXCIsXG4gICAgICBzdHJpbmcgPSAoc2lnbiA/IC12YWx1ZSA6IHZhbHVlKSArIFwiXCIsXG4gICAgICBsZW5ndGggPSBzdHJpbmcubGVuZ3RoO1xuICByZXR1cm4gc2lnbiArIChsZW5ndGggPCB3aWR0aCA/IG5ldyBBcnJheSh3aWR0aCAtIGxlbmd0aCArIDEpLmpvaW4oZmlsbCkgKyBzdHJpbmcgOiBzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiByZXF1b3RlKHMpIHtcbiAgcmV0dXJuIHMucmVwbGFjZShyZXF1b3RlUmUsIFwiXFxcXCQmXCIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRSZShuYW1lcykge1xuICByZXR1cm4gbmV3IFJlZ0V4cChcIl4oPzpcIiArIG5hbWVzLm1hcChyZXF1b3RlKS5qb2luKFwifFwiKSArIFwiKVwiLCBcImlcIik7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdExvb2t1cChuYW1lcykge1xuICB2YXIgbWFwID0ge30sIGkgPSAtMSwgbiA9IG5hbWVzLmxlbmd0aDtcbiAgd2hpbGUgKCsraSA8IG4pIG1hcFtuYW1lc1tpXS50b0xvd2VyQ2FzZSgpXSA9IGk7XG4gIHJldHVybiBtYXA7XG59XG5cbmZ1bmN0aW9uIHBhcnNlV2Vla2RheU51bWJlclN1bmRheShkLCBzdHJpbmcsIGkpIHtcbiAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMSkpO1xuICByZXR1cm4gbiA/IChkLncgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZVdlZWtkYXlOdW1iZXJNb25kYXkoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDEpKTtcbiAgcmV0dXJuIG4gPyAoZC51ID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VXZWVrTnVtYmVyU3VuZGF5KGQsIHN0cmluZywgaSkge1xuICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gIHJldHVybiBuID8gKGQuVSA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG59XG5cbmZ1bmN0aW9uIHBhcnNlV2Vla051bWJlcklTTyhkLCBzdHJpbmcsIGkpIHtcbiAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICByZXR1cm4gbiA/IChkLlYgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZVdlZWtOdW1iZXJNb25kYXkoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgcmV0dXJuIG4gPyAoZC5XID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VGdWxsWWVhcihkLCBzdHJpbmcsIGkpIHtcbiAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgNCkpO1xuICByZXR1cm4gbiA/IChkLnkgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZVllYXIoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgcmV0dXJuIG4gPyAoZC55ID0gK25bMF0gKyAoK25bMF0gPiA2OCA/IDE5MDAgOiAyMDAwKSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZVpvbmUoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gL14oWil8KFsrLV1cXGRcXGQpKD86Oj8oXFxkXFxkKSk/Ly5leGVjKHN0cmluZy5zbGljZShpLCBpICsgNikpO1xuICByZXR1cm4gbiA/IChkLlogPSBuWzFdID8gMCA6IC0oblsyXSArIChuWzNdIHx8IFwiMDBcIikpLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG59XG5cbmZ1bmN0aW9uIHBhcnNlTW9udGhOdW1iZXIoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgcmV0dXJuIG4gPyAoZC5tID0gblswXSAtIDEsIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VEYXlPZk1vbnRoKGQsIHN0cmluZywgaSkge1xuICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gIHJldHVybiBuID8gKGQuZCA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG59XG5cbmZ1bmN0aW9uIHBhcnNlRGF5T2ZZZWFyKGQsIHN0cmluZywgaSkge1xuICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAzKSk7XG4gIHJldHVybiBuID8gKGQubSA9IDAsIGQuZCA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG59XG5cbmZ1bmN0aW9uIHBhcnNlSG91cjI0KGQsIHN0cmluZywgaSkge1xuICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gIHJldHVybiBuID8gKGQuSCA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG59XG5cbmZ1bmN0aW9uIHBhcnNlTWludXRlcyhkLCBzdHJpbmcsIGkpIHtcbiAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICByZXR1cm4gbiA/IChkLk0gPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xufVxuXG5mdW5jdGlvbiBwYXJzZVNlY29uZHMoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgcmV0dXJuIG4gPyAoZC5TID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VNaWxsaXNlY29uZHMoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDMpKTtcbiAgcmV0dXJuIG4gPyAoZC5MID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VNaWNyb3NlY29uZHMoZCwgc3RyaW5nLCBpKSB7XG4gIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDYpKTtcbiAgcmV0dXJuIG4gPyAoZC5MID0gTWF0aC5mbG9vcihuWzBdIC8gMTAwMCksIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VMaXRlcmFsUGVyY2VudChkLCBzdHJpbmcsIGkpIHtcbiAgdmFyIG4gPSBwZXJjZW50UmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDEpKTtcbiAgcmV0dXJuIG4gPyBpICsgblswXS5sZW5ndGggOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VVbml4VGltZXN0YW1wKGQsIHN0cmluZywgaSkge1xuICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgcmV0dXJuIG4gPyAoZC5RID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbn1cblxuZnVuY3Rpb24gcGFyc2VVbml4VGltZXN0YW1wU2Vjb25kcyhkLCBzdHJpbmcsIGkpIHtcbiAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gIHJldHVybiBuID8gKGQuUSA9ICgrblswXSkgKiAxMDAwLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdERheU9mTW9udGgoZCwgcCkge1xuICByZXR1cm4gcGFkKGQuZ2V0RGF0ZSgpLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0SG91cjI0KGQsIHApIHtcbiAgcmV0dXJuIHBhZChkLmdldEhvdXJzKCksIHAsIDIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRIb3VyMTIoZCwgcCkge1xuICByZXR1cm4gcGFkKGQuZ2V0SG91cnMoKSAlIDEyIHx8IDEyLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0RGF5T2ZZZWFyKGQsIHApIHtcbiAgcmV0dXJuIHBhZCgxICsgZDNUaW1lLnRpbWVEYXkuY291bnQoZDNUaW1lLnRpbWVZZWFyKGQpLCBkKSwgcCwgMyk7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdE1pbGxpc2Vjb25kcyhkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRNaWxsaXNlY29uZHMoKSwgcCwgMyk7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdE1pY3Jvc2Vjb25kcyhkLCBwKSB7XG4gIHJldHVybiBmb3JtYXRNaWxsaXNlY29uZHMoZCwgcCkgKyBcIjAwMFwiO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRNb250aE51bWJlcihkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRNb250aCgpICsgMSwgcCwgMik7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdE1pbnV0ZXMoZCwgcCkge1xuICByZXR1cm4gcGFkKGQuZ2V0TWludXRlcygpLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0U2Vjb25kcyhkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRTZWNvbmRzKCksIHAsIDIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRXZWVrZGF5TnVtYmVyTW9uZGF5KGQpIHtcbiAgdmFyIGRheSA9IGQuZ2V0RGF5KCk7XG4gIHJldHVybiBkYXkgPT09IDAgPyA3IDogZGF5O1xufVxuXG5mdW5jdGlvbiBmb3JtYXRXZWVrTnVtYmVyU3VuZGF5KGQsIHApIHtcbiAgcmV0dXJuIHBhZChkM1RpbWUudGltZVN1bmRheS5jb3VudChkM1RpbWUudGltZVllYXIoZCksIGQpLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0V2Vla051bWJlcklTTyhkLCBwKSB7XG4gIHZhciBkYXkgPSBkLmdldERheSgpO1xuICBkID0gKGRheSA+PSA0IHx8IGRheSA9PT0gMCkgPyBkM1RpbWUudGltZVRodXJzZGF5KGQpIDogZDNUaW1lLnRpbWVUaHVyc2RheS5jZWlsKGQpO1xuICByZXR1cm4gcGFkKGQzVGltZS50aW1lVGh1cnNkYXkuY291bnQoZDNUaW1lLnRpbWVZZWFyKGQpLCBkKSArIChkM1RpbWUudGltZVllYXIoZCkuZ2V0RGF5KCkgPT09IDQpLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0V2Vla2RheU51bWJlclN1bmRheShkKSB7XG4gIHJldHVybiBkLmdldERheSgpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRXZWVrTnVtYmVyTW9uZGF5KGQsIHApIHtcbiAgcmV0dXJuIHBhZChkM1RpbWUudGltZU1vbmRheS5jb3VudChkM1RpbWUudGltZVllYXIoZCksIGQpLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0WWVhcihkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRGdWxsWWVhcigpICUgMTAwLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0RnVsbFllYXIoZCwgcCkge1xuICByZXR1cm4gcGFkKGQuZ2V0RnVsbFllYXIoKSAlIDEwMDAwLCBwLCA0KTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0Wm9uZShkKSB7XG4gIHZhciB6ID0gZC5nZXRUaW1lem9uZU9mZnNldCgpO1xuICByZXR1cm4gKHogPiAwID8gXCItXCIgOiAoeiAqPSAtMSwgXCIrXCIpKVxuICAgICAgKyBwYWQoeiAvIDYwIHwgMCwgXCIwXCIsIDIpXG4gICAgICArIHBhZCh6ICUgNjAsIFwiMFwiLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VVRDRGF5T2ZNb250aChkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRVVENEYXRlKCksIHAsIDIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRVVENIb3VyMjQoZCwgcCkge1xuICByZXR1cm4gcGFkKGQuZ2V0VVRDSG91cnMoKSwgcCwgMik7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFVUQ0hvdXIxMihkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRVVENIb3VycygpICUgMTIgfHwgMTIsIHAsIDIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRVVENEYXlPZlllYXIoZCwgcCkge1xuICByZXR1cm4gcGFkKDEgKyBkM1RpbWUudXRjRGF5LmNvdW50KGQzVGltZS51dGNZZWFyKGQpLCBkKSwgcCwgMyk7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFVUQ01pbGxpc2Vjb25kcyhkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRVVENNaWxsaXNlY29uZHMoKSwgcCwgMyk7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFVUQ01pY3Jvc2Vjb25kcyhkLCBwKSB7XG4gIHJldHVybiBmb3JtYXRVVENNaWxsaXNlY29uZHMoZCwgcCkgKyBcIjAwMFwiO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRVVENNb250aE51bWJlcihkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRVVENNb250aCgpICsgMSwgcCwgMik7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFVUQ01pbnV0ZXMoZCwgcCkge1xuICByZXR1cm4gcGFkKGQuZ2V0VVRDTWludXRlcygpLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VVRDU2Vjb25kcyhkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRVVENTZWNvbmRzKCksIHAsIDIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRVVENXZWVrZGF5TnVtYmVyTW9uZGF5KGQpIHtcbiAgdmFyIGRvdyA9IGQuZ2V0VVRDRGF5KCk7XG4gIHJldHVybiBkb3cgPT09IDAgPyA3IDogZG93O1xufVxuXG5mdW5jdGlvbiBmb3JtYXRVVENXZWVrTnVtYmVyU3VuZGF5KGQsIHApIHtcbiAgcmV0dXJuIHBhZChkM1RpbWUudXRjU3VuZGF5LmNvdW50KGQzVGltZS51dGNZZWFyKGQpLCBkKSwgcCwgMik7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFVUQ1dlZWtOdW1iZXJJU08oZCwgcCkge1xuICB2YXIgZGF5ID0gZC5nZXRVVENEYXkoKTtcbiAgZCA9IChkYXkgPj0gNCB8fCBkYXkgPT09IDApID8gZDNUaW1lLnV0Y1RodXJzZGF5KGQpIDogZDNUaW1lLnV0Y1RodXJzZGF5LmNlaWwoZCk7XG4gIHJldHVybiBwYWQoZDNUaW1lLnV0Y1RodXJzZGF5LmNvdW50KGQzVGltZS51dGNZZWFyKGQpLCBkKSArIChkM1RpbWUudXRjWWVhcihkKS5nZXRVVENEYXkoKSA9PT0gNCksIHAsIDIpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXRVVENXZWVrZGF5TnVtYmVyU3VuZGF5KGQpIHtcbiAgcmV0dXJuIGQuZ2V0VVRDRGF5KCk7XG59XG5cbmZ1bmN0aW9uIGZvcm1hdFVUQ1dlZWtOdW1iZXJNb25kYXkoZCwgcCkge1xuICByZXR1cm4gcGFkKGQzVGltZS51dGNNb25kYXkuY291bnQoZDNUaW1lLnV0Y1llYXIoZCksIGQpLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VVRDWWVhcihkLCBwKSB7XG4gIHJldHVybiBwYWQoZC5nZXRVVENGdWxsWWVhcigpICUgMTAwLCBwLCAyKTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VVRDRnVsbFllYXIoZCwgcCkge1xuICByZXR1cm4gcGFkKGQuZ2V0VVRDRnVsbFllYXIoKSAlIDEwMDAwLCBwLCA0KTtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VVRDWm9uZSgpIHtcbiAgcmV0dXJuIFwiKzAwMDBcIjtcbn1cblxuZnVuY3Rpb24gZm9ybWF0TGl0ZXJhbFBlcmNlbnQoKSB7XG4gIHJldHVybiBcIiVcIjtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VW5peFRpbWVzdGFtcChkKSB7XG4gIHJldHVybiArZDtcbn1cblxuZnVuY3Rpb24gZm9ybWF0VW5peFRpbWVzdGFtcFNlY29uZHMoZCkge1xuICByZXR1cm4gTWF0aC5mbG9vcigrZCAvIDEwMDApO1xufVxuXG52YXIgbG9jYWxlO1xuXG5cblxuXG5cbmRlZmF1bHRMb2NhbGUoe1xuICBkYXRlVGltZTogXCIleCwgJVhcIixcbiAgZGF0ZTogXCIlLW0vJS1kLyVZXCIsXG4gIHRpbWU6IFwiJS1JOiVNOiVTICVwXCIsXG4gIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sXG4gIGRheXM6IFtcIlN1bmRheVwiLCBcIk1vbmRheVwiLCBcIlR1ZXNkYXlcIiwgXCJXZWRuZXNkYXlcIiwgXCJUaHVyc2RheVwiLCBcIkZyaWRheVwiLCBcIlNhdHVyZGF5XCJdLFxuICBzaG9ydERheXM6IFtcIlN1blwiLCBcIk1vblwiLCBcIlR1ZVwiLCBcIldlZFwiLCBcIlRodVwiLCBcIkZyaVwiLCBcIlNhdFwiXSxcbiAgbW9udGhzOiBbXCJKYW51YXJ5XCIsIFwiRmVicnVhcnlcIiwgXCJNYXJjaFwiLCBcIkFwcmlsXCIsIFwiTWF5XCIsIFwiSnVuZVwiLCBcIkp1bHlcIiwgXCJBdWd1c3RcIiwgXCJTZXB0ZW1iZXJcIiwgXCJPY3RvYmVyXCIsIFwiTm92ZW1iZXJcIiwgXCJEZWNlbWJlclwiXSxcbiAgc2hvcnRNb250aHM6IFtcIkphblwiLCBcIkZlYlwiLCBcIk1hclwiLCBcIkFwclwiLCBcIk1heVwiLCBcIkp1blwiLCBcIkp1bFwiLCBcIkF1Z1wiLCBcIlNlcFwiLCBcIk9jdFwiLCBcIk5vdlwiLCBcIkRlY1wiXVxufSk7XG5cbmZ1bmN0aW9uIGRlZmF1bHRMb2NhbGUoZGVmaW5pdGlvbikge1xuICBsb2NhbGUgPSBmb3JtYXRMb2NhbGUoZGVmaW5pdGlvbik7XG4gIGV4cG9ydHMudGltZUZvcm1hdCA9IGxvY2FsZS5mb3JtYXQ7XG4gIGV4cG9ydHMudGltZVBhcnNlID0gbG9jYWxlLnBhcnNlO1xuICBleHBvcnRzLnV0Y0Zvcm1hdCA9IGxvY2FsZS51dGNGb3JtYXQ7XG4gIGV4cG9ydHMudXRjUGFyc2UgPSBsb2NhbGUudXRjUGFyc2U7XG4gIHJldHVybiBsb2NhbGU7XG59XG5cbnZhciBpc29TcGVjaWZpZXIgPSBcIiVZLSVtLSVkVCVIOiVNOiVTLiVMWlwiO1xuXG5mdW5jdGlvbiBmb3JtYXRJc29OYXRpdmUoZGF0ZSkge1xuICByZXR1cm4gZGF0ZS50b0lTT1N0cmluZygpO1xufVxuXG52YXIgZm9ybWF0SXNvID0gRGF0ZS5wcm90b3R5cGUudG9JU09TdHJpbmdcbiAgICA/IGZvcm1hdElzb05hdGl2ZVxuICAgIDogZXhwb3J0cy51dGNGb3JtYXQoaXNvU3BlY2lmaWVyKTtcblxuZnVuY3Rpb24gcGFyc2VJc29OYXRpdmUoc3RyaW5nKSB7XG4gIHZhciBkYXRlID0gbmV3IERhdGUoc3RyaW5nKTtcbiAgcmV0dXJuIGlzTmFOKGRhdGUpID8gbnVsbCA6IGRhdGU7XG59XG5cbnZhciBwYXJzZUlzbyA9ICtuZXcgRGF0ZShcIjIwMDAtMDEtMDFUMDA6MDA6MDAuMDAwWlwiKVxuICAgID8gcGFyc2VJc29OYXRpdmVcbiAgICA6IGV4cG9ydHMudXRjUGFyc2UoaXNvU3BlY2lmaWVyKTtcblxuZXhwb3J0cy50aW1lRm9ybWF0RGVmYXVsdExvY2FsZSA9IGRlZmF1bHRMb2NhbGU7XG5leHBvcnRzLnRpbWVGb3JtYXRMb2NhbGUgPSBmb3JtYXRMb2NhbGU7XG5leHBvcnRzLmlzb0Zvcm1hdCA9IGZvcm1hdElzbztcbmV4cG9ydHMuaXNvUGFyc2UgPSBwYXJzZUlzbztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcblxufSkpKTtcbiIsIi8vIGh0dHBzOi8vZDNqcy5vcmcvZDMtdGltZS8gVmVyc2lvbiAxLjAuOC4gQ29weXJpZ2h0IDIwMTcgTWlrZSBCb3N0b2NrLlxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSkpO1xufSh0aGlzLCAoZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG52YXIgdDAgPSBuZXcgRGF0ZTtcbnZhciB0MSA9IG5ldyBEYXRlO1xuXG5mdW5jdGlvbiBuZXdJbnRlcnZhbChmbG9vcmksIG9mZnNldGksIGNvdW50LCBmaWVsZCkge1xuXG4gIGZ1bmN0aW9uIGludGVydmFsKGRhdGUpIHtcbiAgICByZXR1cm4gZmxvb3JpKGRhdGUgPSBuZXcgRGF0ZSgrZGF0ZSkpLCBkYXRlO1xuICB9XG5cbiAgaW50ZXJ2YWwuZmxvb3IgPSBpbnRlcnZhbDtcblxuICBpbnRlcnZhbC5jZWlsID0gZnVuY3Rpb24oZGF0ZSkge1xuICAgIHJldHVybiBmbG9vcmkoZGF0ZSA9IG5ldyBEYXRlKGRhdGUgLSAxKSksIG9mZnNldGkoZGF0ZSwgMSksIGZsb29yaShkYXRlKSwgZGF0ZTtcbiAgfTtcblxuICBpbnRlcnZhbC5yb3VuZCA9IGZ1bmN0aW9uKGRhdGUpIHtcbiAgICB2YXIgZDAgPSBpbnRlcnZhbChkYXRlKSxcbiAgICAgICAgZDEgPSBpbnRlcnZhbC5jZWlsKGRhdGUpO1xuICAgIHJldHVybiBkYXRlIC0gZDAgPCBkMSAtIGRhdGUgPyBkMCA6IGQxO1xuICB9O1xuXG4gIGludGVydmFsLm9mZnNldCA9IGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgICByZXR1cm4gb2Zmc2V0aShkYXRlID0gbmV3IERhdGUoK2RhdGUpLCBzdGVwID09IG51bGwgPyAxIDogTWF0aC5mbG9vcihzdGVwKSksIGRhdGU7XG4gIH07XG5cbiAgaW50ZXJ2YWwucmFuZ2UgPSBmdW5jdGlvbihzdGFydCwgc3RvcCwgc3RlcCkge1xuICAgIHZhciByYW5nZSA9IFtdLCBwcmV2aW91cztcbiAgICBzdGFydCA9IGludGVydmFsLmNlaWwoc3RhcnQpO1xuICAgIHN0ZXAgPSBzdGVwID09IG51bGwgPyAxIDogTWF0aC5mbG9vcihzdGVwKTtcbiAgICBpZiAoIShzdGFydCA8IHN0b3ApIHx8ICEoc3RlcCA+IDApKSByZXR1cm4gcmFuZ2U7IC8vIGFsc28gaGFuZGxlcyBJbnZhbGlkIERhdGVcbiAgICBkbyByYW5nZS5wdXNoKHByZXZpb3VzID0gbmV3IERhdGUoK3N0YXJ0KSksIG9mZnNldGkoc3RhcnQsIHN0ZXApLCBmbG9vcmkoc3RhcnQpO1xuICAgIHdoaWxlIChwcmV2aW91cyA8IHN0YXJ0ICYmIHN0YXJ0IDwgc3RvcCk7XG4gICAgcmV0dXJuIHJhbmdlO1xuICB9O1xuXG4gIGludGVydmFsLmZpbHRlciA9IGZ1bmN0aW9uKHRlc3QpIHtcbiAgICByZXR1cm4gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgICAgaWYgKGRhdGUgPj0gZGF0ZSkgd2hpbGUgKGZsb29yaShkYXRlKSwgIXRlc3QoZGF0ZSkpIGRhdGUuc2V0VGltZShkYXRlIC0gMSk7XG4gICAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgICAgaWYgKGRhdGUgPj0gZGF0ZSkge1xuICAgICAgICBpZiAoc3RlcCA8IDApIHdoaWxlICgrK3N0ZXAgPD0gMCkge1xuICAgICAgICAgIHdoaWxlIChvZmZzZXRpKGRhdGUsIC0xKSwgIXRlc3QoZGF0ZSkpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tZW1wdHlcbiAgICAgICAgfSBlbHNlIHdoaWxlICgtLXN0ZXAgPj0gMCkge1xuICAgICAgICAgIHdoaWxlIChvZmZzZXRpKGRhdGUsICsxKSwgIXRlc3QoZGF0ZSkpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tZW1wdHlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIGlmIChjb3VudCkge1xuICAgIGludGVydmFsLmNvdW50ID0gZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgICAgdDAuc2V0VGltZSgrc3RhcnQpLCB0MS5zZXRUaW1lKCtlbmQpO1xuICAgICAgZmxvb3JpKHQwKSwgZmxvb3JpKHQxKTtcbiAgICAgIHJldHVybiBNYXRoLmZsb29yKGNvdW50KHQwLCB0MSkpO1xuICAgIH07XG5cbiAgICBpbnRlcnZhbC5ldmVyeSA9IGZ1bmN0aW9uKHN0ZXApIHtcbiAgICAgIHN0ZXAgPSBNYXRoLmZsb29yKHN0ZXApO1xuICAgICAgcmV0dXJuICFpc0Zpbml0ZShzdGVwKSB8fCAhKHN0ZXAgPiAwKSA/IG51bGxcbiAgICAgICAgICA6ICEoc3RlcCA+IDEpID8gaW50ZXJ2YWxcbiAgICAgICAgICA6IGludGVydmFsLmZpbHRlcihmaWVsZFxuICAgICAgICAgICAgICA/IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGZpZWxkKGQpICUgc3RlcCA9PT0gMDsgfVxuICAgICAgICAgICAgICA6IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGludGVydmFsLmNvdW50KDAsIGQpICUgc3RlcCA9PT0gMDsgfSk7XG4gICAgfTtcbiAgfVxuXG4gIHJldHVybiBpbnRlcnZhbDtcbn1cblxudmFyIG1pbGxpc2Vjb25kID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oKSB7XG4gIC8vIG5vb3Bcbn0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgZGF0ZS5zZXRUaW1lKCtkYXRlICsgc3RlcCk7XG59LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gIHJldHVybiBlbmQgLSBzdGFydDtcbn0pO1xuXG4vLyBBbiBvcHRpbWl6ZWQgaW1wbGVtZW50YXRpb24gZm9yIHRoaXMgc2ltcGxlIGNhc2UuXG5taWxsaXNlY29uZC5ldmVyeSA9IGZ1bmN0aW9uKGspIHtcbiAgayA9IE1hdGguZmxvb3Ioayk7XG4gIGlmICghaXNGaW5pdGUoaykgfHwgIShrID4gMCkpIHJldHVybiBudWxsO1xuICBpZiAoIShrID4gMSkpIHJldHVybiBtaWxsaXNlY29uZDtcbiAgcmV0dXJuIG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldFRpbWUoTWF0aC5mbG9vcihkYXRlIC8gaykgKiBrKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0VGltZSgrZGF0ZSArIHN0ZXAgKiBrKTtcbiAgfSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgIHJldHVybiAoZW5kIC0gc3RhcnQpIC8gaztcbiAgfSk7XG59O1xuXG52YXIgbWlsbGlzZWNvbmRzID0gbWlsbGlzZWNvbmQucmFuZ2U7XG5cbnZhciBkdXJhdGlvblNlY29uZCA9IDFlMztcbnZhciBkdXJhdGlvbk1pbnV0ZSA9IDZlNDtcbnZhciBkdXJhdGlvbkhvdXIgPSAzNmU1O1xudmFyIGR1cmF0aW9uRGF5ID0gODY0ZTU7XG52YXIgZHVyYXRpb25XZWVrID0gNjA0OGU1O1xuXG52YXIgc2Vjb25kID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICBkYXRlLnNldFRpbWUoTWF0aC5mbG9vcihkYXRlIC8gZHVyYXRpb25TZWNvbmQpICogZHVyYXRpb25TZWNvbmQpO1xufSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICBkYXRlLnNldFRpbWUoK2RhdGUgKyBzdGVwICogZHVyYXRpb25TZWNvbmQpO1xufSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIGR1cmF0aW9uU2Vjb25kO1xufSwgZnVuY3Rpb24oZGF0ZSkge1xuICByZXR1cm4gZGF0ZS5nZXRVVENTZWNvbmRzKCk7XG59KTtcblxudmFyIHNlY29uZHMgPSBzZWNvbmQucmFuZ2U7XG5cbnZhciBtaW51dGUgPSBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gIGRhdGUuc2V0VGltZShNYXRoLmZsb29yKGRhdGUgLyBkdXJhdGlvbk1pbnV0ZSkgKiBkdXJhdGlvbk1pbnV0ZSk7XG59LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gIGRhdGUuc2V0VGltZSgrZGF0ZSArIHN0ZXAgKiBkdXJhdGlvbk1pbnV0ZSk7XG59LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gIHJldHVybiAoZW5kIC0gc3RhcnQpIC8gZHVyYXRpb25NaW51dGU7XG59LCBmdW5jdGlvbihkYXRlKSB7XG4gIHJldHVybiBkYXRlLmdldE1pbnV0ZXMoKTtcbn0pO1xuXG52YXIgbWludXRlcyA9IG1pbnV0ZS5yYW5nZTtcblxudmFyIGhvdXIgPSBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gIHZhciBvZmZzZXQgPSBkYXRlLmdldFRpbWV6b25lT2Zmc2V0KCkgKiBkdXJhdGlvbk1pbnV0ZSAlIGR1cmF0aW9uSG91cjtcbiAgaWYgKG9mZnNldCA8IDApIG9mZnNldCArPSBkdXJhdGlvbkhvdXI7XG4gIGRhdGUuc2V0VGltZShNYXRoLmZsb29yKCgrZGF0ZSAtIG9mZnNldCkgLyBkdXJhdGlvbkhvdXIpICogZHVyYXRpb25Ib3VyICsgb2Zmc2V0KTtcbn0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgZGF0ZS5zZXRUaW1lKCtkYXRlICsgc3RlcCAqIGR1cmF0aW9uSG91cik7XG59LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gIHJldHVybiAoZW5kIC0gc3RhcnQpIC8gZHVyYXRpb25Ib3VyO1xufSwgZnVuY3Rpb24oZGF0ZSkge1xuICByZXR1cm4gZGF0ZS5nZXRIb3VycygpO1xufSk7XG5cbnZhciBob3VycyA9IGhvdXIucmFuZ2U7XG5cbnZhciBkYXkgPSBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gIGRhdGUuc2V0SG91cnMoMCwgMCwgMCwgMCk7XG59LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gIGRhdGUuc2V0RGF0ZShkYXRlLmdldERhdGUoKSArIHN0ZXApO1xufSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICByZXR1cm4gKGVuZCAtIHN0YXJ0IC0gKGVuZC5nZXRUaW1lem9uZU9mZnNldCgpIC0gc3RhcnQuZ2V0VGltZXpvbmVPZmZzZXQoKSkgKiBkdXJhdGlvbk1pbnV0ZSkgLyBkdXJhdGlvbkRheTtcbn0sIGZ1bmN0aW9uKGRhdGUpIHtcbiAgcmV0dXJuIGRhdGUuZ2V0RGF0ZSgpIC0gMTtcbn0pO1xuXG52YXIgZGF5cyA9IGRheS5yYW5nZTtcblxuZnVuY3Rpb24gd2Vla2RheShpKSB7XG4gIHJldHVybiBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgZGF0ZS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpIC0gKGRhdGUuZ2V0RGF5KCkgKyA3IC0gaSkgJSA3KTtcbiAgICBkYXRlLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpICsgc3RlcCAqIDcpO1xuICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgcmV0dXJuIChlbmQgLSBzdGFydCAtIChlbmQuZ2V0VGltZXpvbmVPZmZzZXQoKSAtIHN0YXJ0LmdldFRpbWV6b25lT2Zmc2V0KCkpICogZHVyYXRpb25NaW51dGUpIC8gZHVyYXRpb25XZWVrO1xuICB9KTtcbn1cblxudmFyIHN1bmRheSA9IHdlZWtkYXkoMCk7XG52YXIgbW9uZGF5ID0gd2Vla2RheSgxKTtcbnZhciB0dWVzZGF5ID0gd2Vla2RheSgyKTtcbnZhciB3ZWRuZXNkYXkgPSB3ZWVrZGF5KDMpO1xudmFyIHRodXJzZGF5ID0gd2Vla2RheSg0KTtcbnZhciBmcmlkYXkgPSB3ZWVrZGF5KDUpO1xudmFyIHNhdHVyZGF5ID0gd2Vla2RheSg2KTtcblxudmFyIHN1bmRheXMgPSBzdW5kYXkucmFuZ2U7XG52YXIgbW9uZGF5cyA9IG1vbmRheS5yYW5nZTtcbnZhciB0dWVzZGF5cyA9IHR1ZXNkYXkucmFuZ2U7XG52YXIgd2VkbmVzZGF5cyA9IHdlZG5lc2RheS5yYW5nZTtcbnZhciB0aHVyc2RheXMgPSB0aHVyc2RheS5yYW5nZTtcbnZhciBmcmlkYXlzID0gZnJpZGF5LnJhbmdlO1xudmFyIHNhdHVyZGF5cyA9IHNhdHVyZGF5LnJhbmdlO1xuXG52YXIgbW9udGggPSBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gIGRhdGUuc2V0RGF0ZSgxKTtcbiAgZGF0ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcbn0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgZGF0ZS5zZXRNb250aChkYXRlLmdldE1vbnRoKCkgKyBzdGVwKTtcbn0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgcmV0dXJuIGVuZC5nZXRNb250aCgpIC0gc3RhcnQuZ2V0TW9udGgoKSArIChlbmQuZ2V0RnVsbFllYXIoKSAtIHN0YXJ0LmdldEZ1bGxZZWFyKCkpICogMTI7XG59LCBmdW5jdGlvbihkYXRlKSB7XG4gIHJldHVybiBkYXRlLmdldE1vbnRoKCk7XG59KTtcblxudmFyIG1vbnRocyA9IG1vbnRoLnJhbmdlO1xuXG52YXIgeWVhciA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgZGF0ZS5zZXRNb250aCgwLCAxKTtcbiAgZGF0ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcbn0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgZGF0ZS5zZXRGdWxsWWVhcihkYXRlLmdldEZ1bGxZZWFyKCkgKyBzdGVwKTtcbn0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgcmV0dXJuIGVuZC5nZXRGdWxsWWVhcigpIC0gc3RhcnQuZ2V0RnVsbFllYXIoKTtcbn0sIGZ1bmN0aW9uKGRhdGUpIHtcbiAgcmV0dXJuIGRhdGUuZ2V0RnVsbFllYXIoKTtcbn0pO1xuXG4vLyBBbiBvcHRpbWl6ZWQgaW1wbGVtZW50YXRpb24gZm9yIHRoaXMgc2ltcGxlIGNhc2UuXG55ZWFyLmV2ZXJ5ID0gZnVuY3Rpb24oaykge1xuICByZXR1cm4gIWlzRmluaXRlKGsgPSBNYXRoLmZsb29yKGspKSB8fCAhKGsgPiAwKSA/IG51bGwgOiBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgZGF0ZS5zZXRGdWxsWWVhcihNYXRoLmZsb29yKGRhdGUuZ2V0RnVsbFllYXIoKSAvIGspICogayk7XG4gICAgZGF0ZS5zZXRNb250aCgwLCAxKTtcbiAgICBkYXRlLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXRGdWxsWWVhcihkYXRlLmdldEZ1bGxZZWFyKCkgKyBzdGVwICogayk7XG4gIH0pO1xufTtcblxudmFyIHllYXJzID0geWVhci5yYW5nZTtcblxudmFyIHV0Y01pbnV0ZSA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgZGF0ZS5zZXRVVENTZWNvbmRzKDAsIDApO1xufSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICBkYXRlLnNldFRpbWUoK2RhdGUgKyBzdGVwICogZHVyYXRpb25NaW51dGUpO1xufSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIGR1cmF0aW9uTWludXRlO1xufSwgZnVuY3Rpb24oZGF0ZSkge1xuICByZXR1cm4gZGF0ZS5nZXRVVENNaW51dGVzKCk7XG59KTtcblxudmFyIHV0Y01pbnV0ZXMgPSB1dGNNaW51dGUucmFuZ2U7XG5cbnZhciB1dGNIb3VyID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICBkYXRlLnNldFVUQ01pbnV0ZXMoMCwgMCwgMCk7XG59LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gIGRhdGUuc2V0VGltZSgrZGF0ZSArIHN0ZXAgKiBkdXJhdGlvbkhvdXIpO1xufSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIGR1cmF0aW9uSG91cjtcbn0sIGZ1bmN0aW9uKGRhdGUpIHtcbiAgcmV0dXJuIGRhdGUuZ2V0VVRDSG91cnMoKTtcbn0pO1xuXG52YXIgdXRjSG91cnMgPSB1dGNIb3VyLnJhbmdlO1xuXG52YXIgdXRjRGF5ID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xufSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICBkYXRlLnNldFVUQ0RhdGUoZGF0ZS5nZXRVVENEYXRlKCkgKyBzdGVwKTtcbn0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgcmV0dXJuIChlbmQgLSBzdGFydCkgLyBkdXJhdGlvbkRheTtcbn0sIGZ1bmN0aW9uKGRhdGUpIHtcbiAgcmV0dXJuIGRhdGUuZ2V0VVRDRGF0ZSgpIC0gMTtcbn0pO1xuXG52YXIgdXRjRGF5cyA9IHV0Y0RheS5yYW5nZTtcblxuZnVuY3Rpb24gdXRjV2Vla2RheShpKSB7XG4gIHJldHVybiBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgZGF0ZS5zZXRVVENEYXRlKGRhdGUuZ2V0VVRDRGF0ZSgpIC0gKGRhdGUuZ2V0VVRDRGF5KCkgKyA3IC0gaSkgJSA3KTtcbiAgICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXRVVENEYXRlKGRhdGUuZ2V0VVRDRGF0ZSgpICsgc3RlcCAqIDcpO1xuICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgcmV0dXJuIChlbmQgLSBzdGFydCkgLyBkdXJhdGlvbldlZWs7XG4gIH0pO1xufVxuXG52YXIgdXRjU3VuZGF5ID0gdXRjV2Vla2RheSgwKTtcbnZhciB1dGNNb25kYXkgPSB1dGNXZWVrZGF5KDEpO1xudmFyIHV0Y1R1ZXNkYXkgPSB1dGNXZWVrZGF5KDIpO1xudmFyIHV0Y1dlZG5lc2RheSA9IHV0Y1dlZWtkYXkoMyk7XG52YXIgdXRjVGh1cnNkYXkgPSB1dGNXZWVrZGF5KDQpO1xudmFyIHV0Y0ZyaWRheSA9IHV0Y1dlZWtkYXkoNSk7XG52YXIgdXRjU2F0dXJkYXkgPSB1dGNXZWVrZGF5KDYpO1xuXG52YXIgdXRjU3VuZGF5cyA9IHV0Y1N1bmRheS5yYW5nZTtcbnZhciB1dGNNb25kYXlzID0gdXRjTW9uZGF5LnJhbmdlO1xudmFyIHV0Y1R1ZXNkYXlzID0gdXRjVHVlc2RheS5yYW5nZTtcbnZhciB1dGNXZWRuZXNkYXlzID0gdXRjV2VkbmVzZGF5LnJhbmdlO1xudmFyIHV0Y1RodXJzZGF5cyA9IHV0Y1RodXJzZGF5LnJhbmdlO1xudmFyIHV0Y0ZyaWRheXMgPSB1dGNGcmlkYXkucmFuZ2U7XG52YXIgdXRjU2F0dXJkYXlzID0gdXRjU2F0dXJkYXkucmFuZ2U7XG5cbnZhciB1dGNNb250aCA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgZGF0ZS5zZXRVVENEYXRlKDEpO1xuICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xufSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICBkYXRlLnNldFVUQ01vbnRoKGRhdGUuZ2V0VVRDTW9udGgoKSArIHN0ZXApO1xufSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICByZXR1cm4gZW5kLmdldFVUQ01vbnRoKCkgLSBzdGFydC5nZXRVVENNb250aCgpICsgKGVuZC5nZXRVVENGdWxsWWVhcigpIC0gc3RhcnQuZ2V0VVRDRnVsbFllYXIoKSkgKiAxMjtcbn0sIGZ1bmN0aW9uKGRhdGUpIHtcbiAgcmV0dXJuIGRhdGUuZ2V0VVRDTW9udGgoKTtcbn0pO1xuXG52YXIgdXRjTW9udGhzID0gdXRjTW9udGgucmFuZ2U7XG5cbnZhciB1dGNZZWFyID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICBkYXRlLnNldFVUQ01vbnRoKDAsIDEpO1xuICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xufSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICBkYXRlLnNldFVUQ0Z1bGxZZWFyKGRhdGUuZ2V0VVRDRnVsbFllYXIoKSArIHN0ZXApO1xufSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICByZXR1cm4gZW5kLmdldFVUQ0Z1bGxZZWFyKCkgLSBzdGFydC5nZXRVVENGdWxsWWVhcigpO1xufSwgZnVuY3Rpb24oZGF0ZSkge1xuICByZXR1cm4gZGF0ZS5nZXRVVENGdWxsWWVhcigpO1xufSk7XG5cbi8vIEFuIG9wdGltaXplZCBpbXBsZW1lbnRhdGlvbiBmb3IgdGhpcyBzaW1wbGUgY2FzZS5cbnV0Y1llYXIuZXZlcnkgPSBmdW5jdGlvbihrKSB7XG4gIHJldHVybiAhaXNGaW5pdGUoayA9IE1hdGguZmxvb3IoaykpIHx8ICEoayA+IDApID8gbnVsbCA6IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKE1hdGguZmxvb3IoZGF0ZS5nZXRVVENGdWxsWWVhcigpIC8gaykgKiBrKTtcbiAgICBkYXRlLnNldFVUQ01vbnRoKDAsIDEpO1xuICAgIGRhdGUuc2V0VVRDSG91cnMoMCwgMCwgMCwgMCk7XG4gIH0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKGRhdGUuZ2V0VVRDRnVsbFllYXIoKSArIHN0ZXAgKiBrKTtcbiAgfSk7XG59O1xuXG52YXIgdXRjWWVhcnMgPSB1dGNZZWFyLnJhbmdlO1xuXG5leHBvcnRzLnRpbWVJbnRlcnZhbCA9IG5ld0ludGVydmFsO1xuZXhwb3J0cy50aW1lTWlsbGlzZWNvbmQgPSBtaWxsaXNlY29uZDtcbmV4cG9ydHMudGltZU1pbGxpc2Vjb25kcyA9IG1pbGxpc2Vjb25kcztcbmV4cG9ydHMudXRjTWlsbGlzZWNvbmQgPSBtaWxsaXNlY29uZDtcbmV4cG9ydHMudXRjTWlsbGlzZWNvbmRzID0gbWlsbGlzZWNvbmRzO1xuZXhwb3J0cy50aW1lU2Vjb25kID0gc2Vjb25kO1xuZXhwb3J0cy50aW1lU2Vjb25kcyA9IHNlY29uZHM7XG5leHBvcnRzLnV0Y1NlY29uZCA9IHNlY29uZDtcbmV4cG9ydHMudXRjU2Vjb25kcyA9IHNlY29uZHM7XG5leHBvcnRzLnRpbWVNaW51dGUgPSBtaW51dGU7XG5leHBvcnRzLnRpbWVNaW51dGVzID0gbWludXRlcztcbmV4cG9ydHMudGltZUhvdXIgPSBob3VyO1xuZXhwb3J0cy50aW1lSG91cnMgPSBob3VycztcbmV4cG9ydHMudGltZURheSA9IGRheTtcbmV4cG9ydHMudGltZURheXMgPSBkYXlzO1xuZXhwb3J0cy50aW1lV2VlayA9IHN1bmRheTtcbmV4cG9ydHMudGltZVdlZWtzID0gc3VuZGF5cztcbmV4cG9ydHMudGltZVN1bmRheSA9IHN1bmRheTtcbmV4cG9ydHMudGltZVN1bmRheXMgPSBzdW5kYXlzO1xuZXhwb3J0cy50aW1lTW9uZGF5ID0gbW9uZGF5O1xuZXhwb3J0cy50aW1lTW9uZGF5cyA9IG1vbmRheXM7XG5leHBvcnRzLnRpbWVUdWVzZGF5ID0gdHVlc2RheTtcbmV4cG9ydHMudGltZVR1ZXNkYXlzID0gdHVlc2RheXM7XG5leHBvcnRzLnRpbWVXZWRuZXNkYXkgPSB3ZWRuZXNkYXk7XG5leHBvcnRzLnRpbWVXZWRuZXNkYXlzID0gd2VkbmVzZGF5cztcbmV4cG9ydHMudGltZVRodXJzZGF5ID0gdGh1cnNkYXk7XG5leHBvcnRzLnRpbWVUaHVyc2RheXMgPSB0aHVyc2RheXM7XG5leHBvcnRzLnRpbWVGcmlkYXkgPSBmcmlkYXk7XG5leHBvcnRzLnRpbWVGcmlkYXlzID0gZnJpZGF5cztcbmV4cG9ydHMudGltZVNhdHVyZGF5ID0gc2F0dXJkYXk7XG5leHBvcnRzLnRpbWVTYXR1cmRheXMgPSBzYXR1cmRheXM7XG5leHBvcnRzLnRpbWVNb250aCA9IG1vbnRoO1xuZXhwb3J0cy50aW1lTW9udGhzID0gbW9udGhzO1xuZXhwb3J0cy50aW1lWWVhciA9IHllYXI7XG5leHBvcnRzLnRpbWVZZWFycyA9IHllYXJzO1xuZXhwb3J0cy51dGNNaW51dGUgPSB1dGNNaW51dGU7XG5leHBvcnRzLnV0Y01pbnV0ZXMgPSB1dGNNaW51dGVzO1xuZXhwb3J0cy51dGNIb3VyID0gdXRjSG91cjtcbmV4cG9ydHMudXRjSG91cnMgPSB1dGNIb3VycztcbmV4cG9ydHMudXRjRGF5ID0gdXRjRGF5O1xuZXhwb3J0cy51dGNEYXlzID0gdXRjRGF5cztcbmV4cG9ydHMudXRjV2VlayA9IHV0Y1N1bmRheTtcbmV4cG9ydHMudXRjV2Vla3MgPSB1dGNTdW5kYXlzO1xuZXhwb3J0cy51dGNTdW5kYXkgPSB1dGNTdW5kYXk7XG5leHBvcnRzLnV0Y1N1bmRheXMgPSB1dGNTdW5kYXlzO1xuZXhwb3J0cy51dGNNb25kYXkgPSB1dGNNb25kYXk7XG5leHBvcnRzLnV0Y01vbmRheXMgPSB1dGNNb25kYXlzO1xuZXhwb3J0cy51dGNUdWVzZGF5ID0gdXRjVHVlc2RheTtcbmV4cG9ydHMudXRjVHVlc2RheXMgPSB1dGNUdWVzZGF5cztcbmV4cG9ydHMudXRjV2VkbmVzZGF5ID0gdXRjV2VkbmVzZGF5O1xuZXhwb3J0cy51dGNXZWRuZXNkYXlzID0gdXRjV2VkbmVzZGF5cztcbmV4cG9ydHMudXRjVGh1cnNkYXkgPSB1dGNUaHVyc2RheTtcbmV4cG9ydHMudXRjVGh1cnNkYXlzID0gdXRjVGh1cnNkYXlzO1xuZXhwb3J0cy51dGNGcmlkYXkgPSB1dGNGcmlkYXk7XG5leHBvcnRzLnV0Y0ZyaWRheXMgPSB1dGNGcmlkYXlzO1xuZXhwb3J0cy51dGNTYXR1cmRheSA9IHV0Y1NhdHVyZGF5O1xuZXhwb3J0cy51dGNTYXR1cmRheXMgPSB1dGNTYXR1cmRheXM7XG5leHBvcnRzLnV0Y01vbnRoID0gdXRjTW9udGg7XG5leHBvcnRzLnV0Y01vbnRocyA9IHV0Y01vbnRocztcbmV4cG9ydHMudXRjWWVhciA9IHV0Y1llYXI7XG5leHBvcnRzLnV0Y1llYXJzID0gdXRjWWVhcnM7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLXRpbWVyLyBWZXJzaW9uIDEuMC43LiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cyddLCBmYWN0b3J5KSA6XG5cdChmYWN0b3J5KChnbG9iYWwuZDMgPSBnbG9iYWwuZDMgfHwge30pKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbnZhciBmcmFtZSA9IDA7XG52YXIgdGltZW91dCA9IDA7XG52YXIgaW50ZXJ2YWwgPSAwO1xudmFyIHBva2VEZWxheSA9IDEwMDA7XG52YXIgdGFza0hlYWQ7XG52YXIgdGFza1RhaWw7XG52YXIgY2xvY2tMYXN0ID0gMDtcbnZhciBjbG9ja05vdyA9IDA7XG52YXIgY2xvY2tTa2V3ID0gMDtcbnZhciBjbG9jayA9IHR5cGVvZiBwZXJmb3JtYW5jZSA9PT0gXCJvYmplY3RcIiAmJiBwZXJmb3JtYW5jZS5ub3cgPyBwZXJmb3JtYW5jZSA6IERhdGU7XG52YXIgc2V0RnJhbWUgPSB0eXBlb2Ygd2luZG93ID09PSBcIm9iamVjdFwiICYmIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPyB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lLmJpbmQod2luZG93KSA6IGZ1bmN0aW9uKGYpIHsgc2V0VGltZW91dChmLCAxNyk7IH07XG5cbmZ1bmN0aW9uIG5vdygpIHtcbiAgcmV0dXJuIGNsb2NrTm93IHx8IChzZXRGcmFtZShjbGVhck5vdyksIGNsb2NrTm93ID0gY2xvY2subm93KCkgKyBjbG9ja1NrZXcpO1xufVxuXG5mdW5jdGlvbiBjbGVhck5vdygpIHtcbiAgY2xvY2tOb3cgPSAwO1xufVxuXG5mdW5jdGlvbiBUaW1lcigpIHtcbiAgdGhpcy5fY2FsbCA9XG4gIHRoaXMuX3RpbWUgPVxuICB0aGlzLl9uZXh0ID0gbnVsbDtcbn1cblxuVGltZXIucHJvdG90eXBlID0gdGltZXIucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogVGltZXIsXG4gIHJlc3RhcnQ6IGZ1bmN0aW9uKGNhbGxiYWNrLCBkZWxheSwgdGltZSkge1xuICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcImNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uXCIpO1xuICAgIHRpbWUgPSAodGltZSA9PSBudWxsID8gbm93KCkgOiArdGltZSkgKyAoZGVsYXkgPT0gbnVsbCA/IDAgOiArZGVsYXkpO1xuICAgIGlmICghdGhpcy5fbmV4dCAmJiB0YXNrVGFpbCAhPT0gdGhpcykge1xuICAgICAgaWYgKHRhc2tUYWlsKSB0YXNrVGFpbC5fbmV4dCA9IHRoaXM7XG4gICAgICBlbHNlIHRhc2tIZWFkID0gdGhpcztcbiAgICAgIHRhc2tUYWlsID0gdGhpcztcbiAgICB9XG4gICAgdGhpcy5fY2FsbCA9IGNhbGxiYWNrO1xuICAgIHRoaXMuX3RpbWUgPSB0aW1lO1xuICAgIHNsZWVwKCk7XG4gIH0sXG4gIHN0b3A6IGZ1bmN0aW9uKCkge1xuICAgIGlmICh0aGlzLl9jYWxsKSB7XG4gICAgICB0aGlzLl9jYWxsID0gbnVsbDtcbiAgICAgIHRoaXMuX3RpbWUgPSBJbmZpbml0eTtcbiAgICAgIHNsZWVwKCk7XG4gICAgfVxuICB9XG59O1xuXG5mdW5jdGlvbiB0aW1lcihjYWxsYmFjaywgZGVsYXksIHRpbWUpIHtcbiAgdmFyIHQgPSBuZXcgVGltZXI7XG4gIHQucmVzdGFydChjYWxsYmFjaywgZGVsYXksIHRpbWUpO1xuICByZXR1cm4gdDtcbn1cblxuZnVuY3Rpb24gdGltZXJGbHVzaCgpIHtcbiAgbm93KCk7IC8vIEdldCB0aGUgY3VycmVudCB0aW1lLCBpZiBub3QgYWxyZWFkeSBzZXQuXG4gICsrZnJhbWU7IC8vIFByZXRlbmQgd2XigJl2ZSBzZXQgYW4gYWxhcm0sIGlmIHdlIGhhdmVu4oCZdCBhbHJlYWR5LlxuICB2YXIgdCA9IHRhc2tIZWFkLCBlO1xuICB3aGlsZSAodCkge1xuICAgIGlmICgoZSA9IGNsb2NrTm93IC0gdC5fdGltZSkgPj0gMCkgdC5fY2FsbC5jYWxsKG51bGwsIGUpO1xuICAgIHQgPSB0Ll9uZXh0O1xuICB9XG4gIC0tZnJhbWU7XG59XG5cbmZ1bmN0aW9uIHdha2UoKSB7XG4gIGNsb2NrTm93ID0gKGNsb2NrTGFzdCA9IGNsb2NrLm5vdygpKSArIGNsb2NrU2tldztcbiAgZnJhbWUgPSB0aW1lb3V0ID0gMDtcbiAgdHJ5IHtcbiAgICB0aW1lckZsdXNoKCk7XG4gIH0gZmluYWxseSB7XG4gICAgZnJhbWUgPSAwO1xuICAgIG5hcCgpO1xuICAgIGNsb2NrTm93ID0gMDtcbiAgfVxufVxuXG5mdW5jdGlvbiBwb2tlKCkge1xuICB2YXIgbm93ID0gY2xvY2subm93KCksIGRlbGF5ID0gbm93IC0gY2xvY2tMYXN0O1xuICBpZiAoZGVsYXkgPiBwb2tlRGVsYXkpIGNsb2NrU2tldyAtPSBkZWxheSwgY2xvY2tMYXN0ID0gbm93O1xufVxuXG5mdW5jdGlvbiBuYXAoKSB7XG4gIHZhciB0MCwgdDEgPSB0YXNrSGVhZCwgdDIsIHRpbWUgPSBJbmZpbml0eTtcbiAgd2hpbGUgKHQxKSB7XG4gICAgaWYgKHQxLl9jYWxsKSB7XG4gICAgICBpZiAodGltZSA+IHQxLl90aW1lKSB0aW1lID0gdDEuX3RpbWU7XG4gICAgICB0MCA9IHQxLCB0MSA9IHQxLl9uZXh0O1xuICAgIH0gZWxzZSB7XG4gICAgICB0MiA9IHQxLl9uZXh0LCB0MS5fbmV4dCA9IG51bGw7XG4gICAgICB0MSA9IHQwID8gdDAuX25leHQgPSB0MiA6IHRhc2tIZWFkID0gdDI7XG4gICAgfVxuICB9XG4gIHRhc2tUYWlsID0gdDA7XG4gIHNsZWVwKHRpbWUpO1xufVxuXG5mdW5jdGlvbiBzbGVlcCh0aW1lKSB7XG4gIGlmIChmcmFtZSkgcmV0dXJuOyAvLyBTb29uZXN0IGFsYXJtIGFscmVhZHkgc2V0LCBvciB3aWxsIGJlLlxuICBpZiAodGltZW91dCkgdGltZW91dCA9IGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgdmFyIGRlbGF5ID0gdGltZSAtIGNsb2NrTm93OyAvLyBTdHJpY3RseSBsZXNzIHRoYW4gaWYgd2UgcmVjb21wdXRlZCBjbG9ja05vdy5cbiAgaWYgKGRlbGF5ID4gMjQpIHtcbiAgICBpZiAodGltZSA8IEluZmluaXR5KSB0aW1lb3V0ID0gc2V0VGltZW91dCh3YWtlLCB0aW1lIC0gY2xvY2subm93KCkgLSBjbG9ja1NrZXcpO1xuICAgIGlmIChpbnRlcnZhbCkgaW50ZXJ2YWwgPSBjbGVhckludGVydmFsKGludGVydmFsKTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoIWludGVydmFsKSBjbG9ja0xhc3QgPSBjbG9jay5ub3coKSwgaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChwb2tlLCBwb2tlRGVsYXkpO1xuICAgIGZyYW1lID0gMSwgc2V0RnJhbWUod2FrZSk7XG4gIH1cbn1cblxudmFyIHRpbWVvdXQkMSA9IGZ1bmN0aW9uKGNhbGxiYWNrLCBkZWxheSwgdGltZSkge1xuICB2YXIgdCA9IG5ldyBUaW1lcjtcbiAgZGVsYXkgPSBkZWxheSA9PSBudWxsID8gMCA6ICtkZWxheTtcbiAgdC5yZXN0YXJ0KGZ1bmN0aW9uKGVsYXBzZWQpIHtcbiAgICB0LnN0b3AoKTtcbiAgICBjYWxsYmFjayhlbGFwc2VkICsgZGVsYXkpO1xuICB9LCBkZWxheSwgdGltZSk7XG4gIHJldHVybiB0O1xufTtcblxudmFyIGludGVydmFsJDEgPSBmdW5jdGlvbihjYWxsYmFjaywgZGVsYXksIHRpbWUpIHtcbiAgdmFyIHQgPSBuZXcgVGltZXIsIHRvdGFsID0gZGVsYXk7XG4gIGlmIChkZWxheSA9PSBudWxsKSByZXR1cm4gdC5yZXN0YXJ0KGNhbGxiYWNrLCBkZWxheSwgdGltZSksIHQ7XG4gIGRlbGF5ID0gK2RlbGF5LCB0aW1lID0gdGltZSA9PSBudWxsID8gbm93KCkgOiArdGltZTtcbiAgdC5yZXN0YXJ0KGZ1bmN0aW9uIHRpY2soZWxhcHNlZCkge1xuICAgIGVsYXBzZWQgKz0gdG90YWw7XG4gICAgdC5yZXN0YXJ0KHRpY2ssIHRvdGFsICs9IGRlbGF5LCB0aW1lKTtcbiAgICBjYWxsYmFjayhlbGFwc2VkKTtcbiAgfSwgZGVsYXksIHRpbWUpO1xuICByZXR1cm4gdDtcbn07XG5cbmV4cG9ydHMubm93ID0gbm93O1xuZXhwb3J0cy50aW1lciA9IHRpbWVyO1xuZXhwb3J0cy50aW1lckZsdXNoID0gdGltZXJGbHVzaDtcbmV4cG9ydHMudGltZW91dCA9IHRpbWVvdXQkMTtcbmV4cG9ydHMuaW50ZXJ2YWwgPSBpbnRlcnZhbCQxO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gZDMudGlwXG4vLyBDb3B5cmlnaHQgKGMpIDIwMTMgSnVzdGluIFBhbG1lclxuLy9cbi8vIFRvb2x0aXBzIGZvciBkMy5qcyBTVkcgdmlzdWFsaXphdGlvbnNcblxuKGZ1bmN0aW9uIChyb290LCBmYWN0b3J5KSB7XG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAvLyBBTUQuIFJlZ2lzdGVyIGFzIGFuIGFub255bW91cyBtb2R1bGUgd2l0aCBkMyBhcyBhIGRlcGVuZGVuY3kuXG4gICAgZGVmaW5lKFsnZDMnXSwgZmFjdG9yeSlcbiAgfSBlbHNlIGlmICh0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgIC8vIENvbW1vbkpTXG4gICAgdmFyIGQzID0gcmVxdWlyZSgnZDMnKVxuICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShkMylcbiAgfSBlbHNlIHtcbiAgICAvLyBCcm93c2VyIGdsb2JhbC5cbiAgICByb290LmQzLnRpcCA9IGZhY3Rvcnkocm9vdC5kMylcbiAgfVxufSh0aGlzLCBmdW5jdGlvbiAoZDMpIHtcblxuICAvLyBQdWJsaWMgLSBjb250cnVjdHMgYSBuZXcgdG9vbHRpcFxuICAvL1xuICAvLyBSZXR1cm5zIGEgdGlwXG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgZGlyZWN0aW9uID0gZDNfdGlwX2RpcmVjdGlvbixcbiAgICAgICAgb2Zmc2V0ICAgID0gZDNfdGlwX29mZnNldCxcbiAgICAgICAgaHRtbCAgICAgID0gZDNfdGlwX2h0bWwsXG4gICAgICAgIG5vZGUgICAgICA9IGluaXROb2RlKCksXG4gICAgICAgIHN2ZyAgICAgICA9IG51bGwsXG4gICAgICAgIHBvaW50ICAgICA9IG51bGwsXG4gICAgICAgIHRhcmdldCAgICA9IG51bGxcblxuICAgIGZ1bmN0aW9uIHRpcCh2aXMpIHtcbiAgICAgIHN2ZyA9IGdldFNWR05vZGUodmlzKVxuICAgICAgcG9pbnQgPSBzdmcuY3JlYXRlU1ZHUG9pbnQoKVxuICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChub2RlKVxuICAgIH1cblxuICAgIC8vIFB1YmxpYyAtIHNob3cgdGhlIHRvb2x0aXAgb24gdGhlIHNjcmVlblxuICAgIC8vXG4gICAgLy8gUmV0dXJucyBhIHRpcFxuICAgIHRpcC5zaG93ID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cylcbiAgICAgIGlmKGFyZ3NbYXJncy5sZW5ndGggLSAxXSBpbnN0YW5jZW9mIFNWR0VsZW1lbnQpIHRhcmdldCA9IGFyZ3MucG9wKClcblxuICAgICAgdmFyIGNvbnRlbnQgPSBodG1sLmFwcGx5KHRoaXMsIGFyZ3MpLFxuICAgICAgICAgIHBvZmZzZXQgPSBvZmZzZXQuYXBwbHkodGhpcywgYXJncyksXG4gICAgICAgICAgZGlyICAgICA9IGRpcmVjdGlvbi5hcHBseSh0aGlzLCBhcmdzKSxcbiAgICAgICAgICBub2RlbCAgID0gZ2V0Tm9kZUVsKCksXG4gICAgICAgICAgaSAgICAgICA9IGRpcmVjdGlvbnMubGVuZ3RoLFxuICAgICAgICAgIGNvb3JkcyxcbiAgICAgICAgICBzY3JvbGxUb3AgID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbFRvcCB8fCBkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCxcbiAgICAgICAgICBzY3JvbGxMZWZ0ID0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnNjcm9sbExlZnQgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0XG5cbiAgICAgIG5vZGVsLmh0bWwoY29udGVudClcbiAgICAgICAgLnN0eWxlKCdvcGFjaXR5JywgMSkuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ2FsbCcpXG5cbiAgICAgIHdoaWxlKGktLSkgbm9kZWwuY2xhc3NlZChkaXJlY3Rpb25zW2ldLCBmYWxzZSlcbiAgICAgIGNvb3JkcyA9IGRpcmVjdGlvbl9jYWxsYmFja3MuZ2V0KGRpcikuYXBwbHkodGhpcylcbiAgICAgIG5vZGVsLmNsYXNzZWQoZGlyLCB0cnVlKVxuICAgICAgXHQuc3R5bGUoJ3RvcCcsIChjb29yZHMudG9wICsgIHBvZmZzZXRbMF0pICsgc2Nyb2xsVG9wICsgJ3B4JylcbiAgICAgIFx0LnN0eWxlKCdsZWZ0JywgKGNvb3Jkcy5sZWZ0ICsgcG9mZnNldFsxXSkgKyBzY3JvbGxMZWZ0ICsgJ3B4JylcblxuICAgICAgcmV0dXJuIHRpcDtcbiAgICB9O1xuXG4gICAgLy8gUHVibGljIC0gaGlkZSB0aGUgdG9vbHRpcFxuICAgIC8vXG4gICAgLy8gUmV0dXJucyBhIHRpcFxuICAgIHRpcC5oaWRlID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbm9kZWwgPSBnZXROb2RlRWwoKVxuICAgICAgbm9kZWwuc3R5bGUoJ29wYWNpdHknLCAwKS5zdHlsZSgncG9pbnRlci1ldmVudHMnLCAnbm9uZScpXG4gICAgICByZXR1cm4gdGlwXG4gICAgfVxuXG4gICAgLy8gUHVibGljOiBQcm94eSBhdHRyIGNhbGxzIHRvIHRoZSBkMyB0aXAgY29udGFpbmVyLiAgU2V0cyBvciBnZXRzIGF0dHJpYnV0ZSB2YWx1ZS5cbiAgICAvL1xuICAgIC8vIG4gLSBuYW1lIG9mIHRoZSBhdHRyaWJ1dGVcbiAgICAvLyB2IC0gdmFsdWUgb2YgdGhlIGF0dHJpYnV0ZVxuICAgIC8vXG4gICAgLy8gUmV0dXJucyB0aXAgb3IgYXR0cmlidXRlIHZhbHVlXG4gICAgdGlwLmF0dHIgPSBmdW5jdGlvbihuLCB2KSB7XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIgJiYgdHlwZW9mIG4gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBnZXROb2RlRWwoKS5hdHRyKG4pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgYXJncyA9ICBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpXG4gICAgICAgIGQzLnNlbGVjdGlvbi5wcm90b3R5cGUuYXR0ci5hcHBseShnZXROb2RlRWwoKSwgYXJncylcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpcFxuICAgIH1cblxuICAgIC8vIFB1YmxpYzogUHJveHkgc3R5bGUgY2FsbHMgdG8gdGhlIGQzIHRpcCBjb250YWluZXIuICBTZXRzIG9yIGdldHMgYSBzdHlsZSB2YWx1ZS5cbiAgICAvL1xuICAgIC8vIG4gLSBuYW1lIG9mIHRoZSBwcm9wZXJ0eVxuICAgIC8vIHYgLSB2YWx1ZSBvZiB0aGUgcHJvcGVydHlcbiAgICAvL1xuICAgIC8vIFJldHVybnMgdGlwIG9yIHN0eWxlIHByb3BlcnR5IHZhbHVlXG4gICAgdGlwLnN0eWxlID0gZnVuY3Rpb24obiwgdikge1xuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAyICYmIHR5cGVvZiBuID09PSAnc3RyaW5nJykge1xuICAgICAgICByZXR1cm4gZ2V0Tm9kZUVsKCkuc3R5bGUobilcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKVxuICAgICAgICBkMy5zZWxlY3Rpb24ucHJvdG90eXBlLnN0eWxlLmFwcGx5KGdldE5vZGVFbCgpLCBhcmdzKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGlwXG4gICAgfVxuXG4gICAgLy8gUHVibGljOiBTZXQgb3IgZ2V0IHRoZSBkaXJlY3Rpb24gb2YgdGhlIHRvb2x0aXBcbiAgICAvL1xuICAgIC8vIHYgLSBPbmUgb2Ygbihub3J0aCksIHMoc291dGgpLCBlKGVhc3QpLCBvciB3KHdlc3QpLCBudyhub3J0aHdlc3QpLFxuICAgIC8vICAgICBzdyhzb3V0aHdlc3QpLCBuZShub3J0aGVhc3QpIG9yIHNlKHNvdXRoZWFzdClcbiAgICAvL1xuICAgIC8vIFJldHVybnMgdGlwIG9yIGRpcmVjdGlvblxuICAgIHRpcC5kaXJlY3Rpb24gPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBkaXJlY3Rpb25cbiAgICAgIGRpcmVjdGlvbiA9IHYgPT0gbnVsbCA/IHYgOiBmdW5jdG9yKHYpXG5cbiAgICAgIHJldHVybiB0aXBcbiAgICB9XG5cbiAgICAvLyBQdWJsaWM6IFNldHMgb3IgZ2V0cyB0aGUgb2Zmc2V0IG9mIHRoZSB0aXBcbiAgICAvL1xuICAgIC8vIHYgLSBBcnJheSBvZiBbeCwgeV0gb2Zmc2V0XG4gICAgLy9cbiAgICAvLyBSZXR1cm5zIG9mZnNldCBvclxuICAgIHRpcC5vZmZzZXQgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBvZmZzZXRcbiAgICAgIG9mZnNldCA9IHYgPT0gbnVsbCA/IHYgOiBmdW5jdG9yKHYpXG5cbiAgICAgIHJldHVybiB0aXBcbiAgICB9XG5cbiAgICAvLyBQdWJsaWM6IHNldHMgb3IgZ2V0cyB0aGUgaHRtbCB2YWx1ZSBvZiB0aGUgdG9vbHRpcFxuICAgIC8vXG4gICAgLy8gdiAtIFN0cmluZyB2YWx1ZSBvZiB0aGUgdGlwXG4gICAgLy9cbiAgICAvLyBSZXR1cm5zIGh0bWwgdmFsdWUgb3IgdGlwXG4gICAgdGlwLmh0bWwgPSBmdW5jdGlvbih2KSB7XG4gICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHJldHVybiBodG1sXG4gICAgICBodG1sID0gdiA9PSBudWxsID8gdiA6IGZ1bmN0b3IodilcblxuICAgICAgcmV0dXJuIHRpcFxuICAgIH1cblxuICAgIC8vIFB1YmxpYzogZGVzdHJveXMgdGhlIHRvb2x0aXAgYW5kIHJlbW92ZXMgaXQgZnJvbSB0aGUgRE9NXG4gICAgLy9cbiAgICAvLyBSZXR1cm5zIGEgdGlwXG4gICAgdGlwLmRlc3Ryb3kgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmKG5vZGUpIHtcbiAgICAgICAgZ2V0Tm9kZUVsKCkucmVtb3ZlKCk7XG4gICAgICAgIG5vZGUgPSBudWxsO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRpcDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkM190aXBfZGlyZWN0aW9uKCkgeyByZXR1cm4gJ24nIH1cbiAgICBmdW5jdGlvbiBkM190aXBfb2Zmc2V0KCkgeyByZXR1cm4gWzAsIDBdIH1cbiAgICBmdW5jdGlvbiBkM190aXBfaHRtbCgpIHsgcmV0dXJuICcgJyB9XG5cbiAgICB2YXIgZGlyZWN0aW9uX2NhbGxiYWNrcyA9IGQzLm1hcCh7XG4gICAgICBuOiAgZGlyZWN0aW9uX24sXG4gICAgICBzOiAgZGlyZWN0aW9uX3MsXG4gICAgICBlOiAgZGlyZWN0aW9uX2UsXG4gICAgICB3OiAgZGlyZWN0aW9uX3csXG4gICAgICBudzogZGlyZWN0aW9uX253LFxuICAgICAgbmU6IGRpcmVjdGlvbl9uZSxcbiAgICAgIHN3OiBkaXJlY3Rpb25fc3csXG4gICAgICBzZTogZGlyZWN0aW9uX3NlXG4gICAgfSksXG5cbiAgICBkaXJlY3Rpb25zID0gZGlyZWN0aW9uX2NhbGxiYWNrcy5rZXlzKClcblxuICAgIGZ1bmN0aW9uIGRpcmVjdGlvbl9uKCkge1xuICAgICAgdmFyIGJib3ggPSBnZXRTY3JlZW5CQm94KClcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogIGJib3gubi55IC0gbm9kZS5vZmZzZXRIZWlnaHQsXG4gICAgICAgIGxlZnQ6IGJib3gubi54IC0gbm9kZS5vZmZzZXRXaWR0aCAvIDJcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkaXJlY3Rpb25fcygpIHtcbiAgICAgIHZhciBiYm94ID0gZ2V0U2NyZWVuQkJveCgpXG4gICAgICByZXR1cm4ge1xuICAgICAgICB0b3A6ICBiYm94LnMueSxcbiAgICAgICAgbGVmdDogYmJveC5zLnggLSBub2RlLm9mZnNldFdpZHRoIC8gMlxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRpcmVjdGlvbl9lKCkge1xuICAgICAgdmFyIGJib3ggPSBnZXRTY3JlZW5CQm94KClcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogIGJib3guZS55IC0gbm9kZS5vZmZzZXRIZWlnaHQgLyAyLFxuICAgICAgICBsZWZ0OiBiYm94LmUueFxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRpcmVjdGlvbl93KCkge1xuICAgICAgdmFyIGJib3ggPSBnZXRTY3JlZW5CQm94KClcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRvcDogIGJib3gudy55IC0gbm9kZS5vZmZzZXRIZWlnaHQgLyAyLFxuICAgICAgICBsZWZ0OiBiYm94LncueCAtIG5vZGUub2Zmc2V0V2lkdGhcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkaXJlY3Rpb25fbncoKSB7XG4gICAgICB2YXIgYmJveCA9IGdldFNjcmVlbkJCb3goKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiAgYmJveC5udy55IC0gbm9kZS5vZmZzZXRIZWlnaHQsXG4gICAgICAgIGxlZnQ6IGJib3gubncueCAtIG5vZGUub2Zmc2V0V2lkdGhcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkaXJlY3Rpb25fbmUoKSB7XG4gICAgICB2YXIgYmJveCA9IGdldFNjcmVlbkJCb3goKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiAgYmJveC5uZS55IC0gbm9kZS5vZmZzZXRIZWlnaHQsXG4gICAgICAgIGxlZnQ6IGJib3gubmUueFxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRpcmVjdGlvbl9zdygpIHtcbiAgICAgIHZhciBiYm94ID0gZ2V0U2NyZWVuQkJveCgpXG4gICAgICByZXR1cm4ge1xuICAgICAgICB0b3A6ICBiYm94LnN3LnksXG4gICAgICAgIGxlZnQ6IGJib3guc3cueCAtIG5vZGUub2Zmc2V0V2lkdGhcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkaXJlY3Rpb25fc2UoKSB7XG4gICAgICB2YXIgYmJveCA9IGdldFNjcmVlbkJCb3goKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdG9wOiAgYmJveC5zZS55LFxuICAgICAgICBsZWZ0OiBiYm94LmUueFxuICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluaXROb2RlKCkge1xuICAgICAgdmFyIG5vZGUgPSBkMy5zZWxlY3QoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpO1xuICAgICAgbm9kZS5zdHlsZSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKS5zdHlsZSgndG9wJywgMCkuc3R5bGUoJ29wYWNpdHknLCAwKVxuICAgICAgXHQuc3R5bGUoJ3BvaW50ZXItZXZlbnRzJywgJ25vbmUnKS5zdHlsZSgnYm94LXNpemluZycsICdib3JkZXItYm94JylcblxuICAgICAgcmV0dXJuIG5vZGUubm9kZSgpXG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U1ZHTm9kZShlbCkge1xuICAgICAgZWwgPSBlbC5ub2RlKClcbiAgICAgIGlmKGVsLnRhZ05hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ3N2ZycpXG4gICAgICAgIHJldHVybiBlbFxuXG4gICAgICByZXR1cm4gZWwub3duZXJTVkdFbGVtZW50XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Tm9kZUVsKCkge1xuICAgICAgaWYobm9kZSA9PT0gbnVsbCkge1xuICAgICAgICBub2RlID0gaW5pdE5vZGUoKTtcbiAgICAgICAgLy8gcmUtYWRkIG5vZGUgdG8gRE9NXG4gICAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQobm9kZSk7XG4gICAgICB9O1xuICAgICAgcmV0dXJuIGQzLnNlbGVjdChub2RlKTtcbiAgICB9XG5cbiAgICAvLyBQcml2YXRlIC0gZ2V0cyB0aGUgc2NyZWVuIGNvb3JkaW5hdGVzIG9mIGEgc2hhcGVcbiAgICAvL1xuICAgIC8vIEdpdmVuIGEgc2hhcGUgb24gdGhlIHNjcmVlbiwgd2lsbCByZXR1cm4gYW4gU1ZHUG9pbnQgZm9yIHRoZSBkaXJlY3Rpb25zXG4gICAgLy8gbihub3J0aCksIHMoc291dGgpLCBlKGVhc3QpLCB3KHdlc3QpLCBuZShub3J0aGVhc3QpLCBzZShzb3V0aGVhc3QpLCBudyhub3J0aHdlc3QpLFxuICAgIC8vIHN3KHNvdXRod2VzdCkuXG4gICAgLy9cbiAgICAvLyAgICArLSstK1xuICAgIC8vICAgIHwgICB8XG4gICAgLy8gICAgKyAgICtcbiAgICAvLyAgICB8ICAgfFxuICAgIC8vICAgICstKy0rXG4gICAgLy9cbiAgICAvLyBSZXR1cm5zIGFuIE9iamVjdCB7biwgcywgZSwgdywgbncsIHN3LCBuZSwgc2V9XG4gICAgZnVuY3Rpb24gZ2V0U2NyZWVuQkJveCgpIHtcbiAgICAgIHZhciB0YXJnZXRlbCAgID0gdGFyZ2V0IHx8IGQzLmV2ZW50LnRhcmdldDtcblxuICAgICAgd2hpbGUgKCd1bmRlZmluZWQnID09PSB0eXBlb2YgdGFyZ2V0ZWwuZ2V0U2NyZWVuQ1RNICYmICd1bmRlZmluZWQnID09PSB0YXJnZXRlbC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgdGFyZ2V0ZWwgPSB0YXJnZXRlbC5wYXJlbnROb2RlO1xuICAgICAgfVxuXG4gICAgICB2YXIgYmJveCAgICAgICA9IHt9LFxuICAgICAgICAgIG1hdHJpeCAgICAgPSB0YXJnZXRlbC5nZXRTY3JlZW5DVE0oKSxcbiAgICAgICAgICB0YmJveCAgICAgID0gdGFyZ2V0ZWwuZ2V0QkJveCgpLFxuICAgICAgICAgIHdpZHRoICAgICAgPSB0YmJveC53aWR0aCxcbiAgICAgICAgICBoZWlnaHQgICAgID0gdGJib3guaGVpZ2h0LFxuICAgICAgICAgIHggICAgICAgICAgPSB0YmJveC54LFxuICAgICAgICAgIHkgICAgICAgICAgPSB0YmJveC55XG5cbiAgICAgIHBvaW50LnggPSB4XG4gICAgICBwb2ludC55ID0geVxuICAgICAgYmJveC5udyA9IHBvaW50Lm1hdHJpeFRyYW5zZm9ybShtYXRyaXgpXG4gICAgICBwb2ludC54ICs9IHdpZHRoXG4gICAgICBiYm94Lm5lID0gcG9pbnQubWF0cml4VHJhbnNmb3JtKG1hdHJpeClcbiAgICAgIHBvaW50LnkgKz0gaGVpZ2h0XG4gICAgICBiYm94LnNlID0gcG9pbnQubWF0cml4VHJhbnNmb3JtKG1hdHJpeClcbiAgICAgIHBvaW50LnggLT0gd2lkdGhcbiAgICAgIGJib3guc3cgPSBwb2ludC5tYXRyaXhUcmFuc2Zvcm0obWF0cml4KVxuICAgICAgcG9pbnQueSAtPSBoZWlnaHQgLyAyXG4gICAgICBiYm94LncgID0gcG9pbnQubWF0cml4VHJhbnNmb3JtKG1hdHJpeClcbiAgICAgIHBvaW50LnggKz0gd2lkdGhcbiAgICAgIGJib3guZSA9IHBvaW50Lm1hdHJpeFRyYW5zZm9ybShtYXRyaXgpXG4gICAgICBwb2ludC54IC09IHdpZHRoIC8gMlxuICAgICAgcG9pbnQueSAtPSBoZWlnaHQgLyAyXG4gICAgICBiYm94Lm4gPSBwb2ludC5tYXRyaXhUcmFuc2Zvcm0obWF0cml4KVxuICAgICAgcG9pbnQueSArPSBoZWlnaHRcbiAgICAgIGJib3gucyA9IHBvaW50Lm1hdHJpeFRyYW5zZm9ybShtYXRyaXgpXG5cbiAgICAgIHJldHVybiBiYm94XG4gICAgfVxuICAgIFxuICAgIC8vIFByaXZhdGUgLSByZXBsYWNlIEQzSlMgMy5YIGQzLmZ1bmN0b3IoKSBmdW5jdGlvblxuICAgIGZ1bmN0aW9uIGZ1bmN0b3Iodikge1xuICAgIFx0cmV0dXJuIHR5cGVvZiB2ID09PSBcImZ1bmN0aW9uXCIgPyB2IDogZnVuY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiB2XG4gICAgXHR9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRpcFxuICB9O1xuXG59KSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLXRyYW5zaXRpb24vIFZlcnNpb24gMS4xLjEuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cywgcmVxdWlyZSgnZDMtc2VsZWN0aW9uJyksIHJlcXVpcmUoJ2QzLWRpc3BhdGNoJyksIHJlcXVpcmUoJ2QzLXRpbWVyJyksIHJlcXVpcmUoJ2QzLWludGVycG9sYXRlJyksIHJlcXVpcmUoJ2QzLWNvbG9yJyksIHJlcXVpcmUoJ2QzLWVhc2UnKSkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ2QzLXNlbGVjdGlvbicsICdkMy1kaXNwYXRjaCcsICdkMy10aW1lcicsICdkMy1pbnRlcnBvbGF0ZScsICdkMy1jb2xvcicsICdkMy1lYXNlJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSksZ2xvYmFsLmQzLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMyxnbG9iYWwuZDMpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzLGQzU2VsZWN0aW9uLGQzRGlzcGF0Y2gsZDNUaW1lcixkM0ludGVycG9sYXRlLGQzQ29sb3IsZDNFYXNlKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGVtcHR5T24gPSBkM0Rpc3BhdGNoLmRpc3BhdGNoKFwic3RhcnRcIiwgXCJlbmRcIiwgXCJpbnRlcnJ1cHRcIik7XG52YXIgZW1wdHlUd2VlbiA9IFtdO1xuXG52YXIgQ1JFQVRFRCA9IDA7XG52YXIgU0NIRURVTEVEID0gMTtcbnZhciBTVEFSVElORyA9IDI7XG52YXIgU1RBUlRFRCA9IDM7XG52YXIgUlVOTklORyA9IDQ7XG52YXIgRU5ESU5HID0gNTtcbnZhciBFTkRFRCA9IDY7XG5cbnZhciBzY2hlZHVsZSA9IGZ1bmN0aW9uKG5vZGUsIG5hbWUsIGlkLCBpbmRleCwgZ3JvdXAsIHRpbWluZykge1xuICB2YXIgc2NoZWR1bGVzID0gbm9kZS5fX3RyYW5zaXRpb247XG4gIGlmICghc2NoZWR1bGVzKSBub2RlLl9fdHJhbnNpdGlvbiA9IHt9O1xuICBlbHNlIGlmIChpZCBpbiBzY2hlZHVsZXMpIHJldHVybjtcbiAgY3JlYXRlKG5vZGUsIGlkLCB7XG4gICAgbmFtZTogbmFtZSxcbiAgICBpbmRleDogaW5kZXgsIC8vIEZvciBjb250ZXh0IGR1cmluZyBjYWxsYmFjay5cbiAgICBncm91cDogZ3JvdXAsIC8vIEZvciBjb250ZXh0IGR1cmluZyBjYWxsYmFjay5cbiAgICBvbjogZW1wdHlPbixcbiAgICB0d2VlbjogZW1wdHlUd2VlbixcbiAgICB0aW1lOiB0aW1pbmcudGltZSxcbiAgICBkZWxheTogdGltaW5nLmRlbGF5LFxuICAgIGR1cmF0aW9uOiB0aW1pbmcuZHVyYXRpb24sXG4gICAgZWFzZTogdGltaW5nLmVhc2UsXG4gICAgdGltZXI6IG51bGwsXG4gICAgc3RhdGU6IENSRUFURURcbiAgfSk7XG59O1xuXG5mdW5jdGlvbiBpbml0KG5vZGUsIGlkKSB7XG4gIHZhciBzY2hlZHVsZSA9IGdldChub2RlLCBpZCk7XG4gIGlmIChzY2hlZHVsZS5zdGF0ZSA+IENSRUFURUQpIHRocm93IG5ldyBFcnJvcihcInRvbyBsYXRlOyBhbHJlYWR5IHNjaGVkdWxlZFwiKTtcbiAgcmV0dXJuIHNjaGVkdWxlO1xufVxuXG5mdW5jdGlvbiBzZXQobm9kZSwgaWQpIHtcbiAgdmFyIHNjaGVkdWxlID0gZ2V0KG5vZGUsIGlkKTtcbiAgaWYgKHNjaGVkdWxlLnN0YXRlID4gU1RBUlRJTkcpIHRocm93IG5ldyBFcnJvcihcInRvbyBsYXRlOyBhbHJlYWR5IHN0YXJ0ZWRcIik7XG4gIHJldHVybiBzY2hlZHVsZTtcbn1cblxuZnVuY3Rpb24gZ2V0KG5vZGUsIGlkKSB7XG4gIHZhciBzY2hlZHVsZSA9IG5vZGUuX190cmFuc2l0aW9uO1xuICBpZiAoIXNjaGVkdWxlIHx8ICEoc2NoZWR1bGUgPSBzY2hlZHVsZVtpZF0pKSB0aHJvdyBuZXcgRXJyb3IoXCJ0cmFuc2l0aW9uIG5vdCBmb3VuZFwiKTtcbiAgcmV0dXJuIHNjaGVkdWxlO1xufVxuXG5mdW5jdGlvbiBjcmVhdGUobm9kZSwgaWQsIHNlbGYpIHtcbiAgdmFyIHNjaGVkdWxlcyA9IG5vZGUuX190cmFuc2l0aW9uLFxuICAgICAgdHdlZW47XG5cbiAgLy8gSW5pdGlhbGl6ZSB0aGUgc2VsZiB0aW1lciB3aGVuIHRoZSB0cmFuc2l0aW9uIGlzIGNyZWF0ZWQuXG4gIC8vIE5vdGUgdGhlIGFjdHVhbCBkZWxheSBpcyBub3Qga25vd24gdW50aWwgdGhlIGZpcnN0IGNhbGxiYWNrIVxuICBzY2hlZHVsZXNbaWRdID0gc2VsZjtcbiAgc2VsZi50aW1lciA9IGQzVGltZXIudGltZXIoc2NoZWR1bGUsIDAsIHNlbGYudGltZSk7XG5cbiAgZnVuY3Rpb24gc2NoZWR1bGUoZWxhcHNlZCkge1xuICAgIHNlbGYuc3RhdGUgPSBTQ0hFRFVMRUQ7XG4gICAgc2VsZi50aW1lci5yZXN0YXJ0KHN0YXJ0LCBzZWxmLmRlbGF5LCBzZWxmLnRpbWUpO1xuXG4gICAgLy8gSWYgdGhlIGVsYXBzZWQgZGVsYXkgaXMgbGVzcyB0aGFuIG91ciBmaXJzdCBzbGVlcCwgc3RhcnQgaW1tZWRpYXRlbHkuXG4gICAgaWYgKHNlbGYuZGVsYXkgPD0gZWxhcHNlZCkgc3RhcnQoZWxhcHNlZCAtIHNlbGYuZGVsYXkpO1xuICB9XG5cbiAgZnVuY3Rpb24gc3RhcnQoZWxhcHNlZCkge1xuICAgIHZhciBpLCBqLCBuLCBvO1xuXG4gICAgLy8gSWYgdGhlIHN0YXRlIGlzIG5vdCBTQ0hFRFVMRUQsIHRoZW4gd2UgcHJldmlvdXNseSBlcnJvcmVkIG9uIHN0YXJ0LlxuICAgIGlmIChzZWxmLnN0YXRlICE9PSBTQ0hFRFVMRUQpIHJldHVybiBzdG9wKCk7XG5cbiAgICBmb3IgKGkgaW4gc2NoZWR1bGVzKSB7XG4gICAgICBvID0gc2NoZWR1bGVzW2ldO1xuICAgICAgaWYgKG8ubmFtZSAhPT0gc2VsZi5uYW1lKSBjb250aW51ZTtcblxuICAgICAgLy8gV2hpbGUgdGhpcyBlbGVtZW50IGFscmVhZHkgaGFzIGEgc3RhcnRpbmcgdHJhbnNpdGlvbiBkdXJpbmcgdGhpcyBmcmFtZSxcbiAgICAgIC8vIGRlZmVyIHN0YXJ0aW5nIGFuIGludGVycnVwdGluZyB0cmFuc2l0aW9uIHVudGlsIHRoYXQgdHJhbnNpdGlvbiBoYXMgYVxuICAgICAgLy8gY2hhbmNlIHRvIHRpY2sgKGFuZCBwb3NzaWJseSBlbmQpOyBzZWUgZDMvZDMtdHJhbnNpdGlvbiM1NCFcbiAgICAgIGlmIChvLnN0YXRlID09PSBTVEFSVEVEKSByZXR1cm4gZDNUaW1lci50aW1lb3V0KHN0YXJ0KTtcblxuICAgICAgLy8gSW50ZXJydXB0IHRoZSBhY3RpdmUgdHJhbnNpdGlvbiwgaWYgYW55LlxuICAgICAgLy8gRGlzcGF0Y2ggdGhlIGludGVycnVwdCBldmVudC5cbiAgICAgIGlmIChvLnN0YXRlID09PSBSVU5OSU5HKSB7XG4gICAgICAgIG8uc3RhdGUgPSBFTkRFRDtcbiAgICAgICAgby50aW1lci5zdG9wKCk7XG4gICAgICAgIG8ub24uY2FsbChcImludGVycnVwdFwiLCBub2RlLCBub2RlLl9fZGF0YV9fLCBvLmluZGV4LCBvLmdyb3VwKTtcbiAgICAgICAgZGVsZXRlIHNjaGVkdWxlc1tpXTtcbiAgICAgIH1cblxuICAgICAgLy8gQ2FuY2VsIGFueSBwcmUtZW1wdGVkIHRyYW5zaXRpb25zLiBObyBpbnRlcnJ1cHQgZXZlbnQgaXMgZGlzcGF0Y2hlZFxuICAgICAgLy8gYmVjYXVzZSB0aGUgY2FuY2VsbGVkIHRyYW5zaXRpb25zIG5ldmVyIHN0YXJ0ZWQuIE5vdGUgdGhhdCB0aGlzIGFsc29cbiAgICAgIC8vIHJlbW92ZXMgdGhpcyB0cmFuc2l0aW9uIGZyb20gdGhlIHBlbmRpbmcgbGlzdCFcbiAgICAgIGVsc2UgaWYgKCtpIDwgaWQpIHtcbiAgICAgICAgby5zdGF0ZSA9IEVOREVEO1xuICAgICAgICBvLnRpbWVyLnN0b3AoKTtcbiAgICAgICAgZGVsZXRlIHNjaGVkdWxlc1tpXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBEZWZlciB0aGUgZmlyc3QgdGljayB0byBlbmQgb2YgdGhlIGN1cnJlbnQgZnJhbWU7IHNlZSBkMy9kMyMxNTc2LlxuICAgIC8vIE5vdGUgdGhlIHRyYW5zaXRpb24gbWF5IGJlIGNhbmNlbGVkIGFmdGVyIHN0YXJ0IGFuZCBiZWZvcmUgdGhlIGZpcnN0IHRpY2shXG4gICAgLy8gTm90ZSB0aGlzIG11c3QgYmUgc2NoZWR1bGVkIGJlZm9yZSB0aGUgc3RhcnQgZXZlbnQ7IHNlZSBkMy9kMy10cmFuc2l0aW9uIzE2IVxuICAgIC8vIEFzc3VtaW5nIHRoaXMgaXMgc3VjY2Vzc2Z1bCwgc3Vic2VxdWVudCBjYWxsYmFja3MgZ28gc3RyYWlnaHQgdG8gdGljay5cbiAgICBkM1RpbWVyLnRpbWVvdXQoZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoc2VsZi5zdGF0ZSA9PT0gU1RBUlRFRCkge1xuICAgICAgICBzZWxmLnN0YXRlID0gUlVOTklORztcbiAgICAgICAgc2VsZi50aW1lci5yZXN0YXJ0KHRpY2ssIHNlbGYuZGVsYXksIHNlbGYudGltZSk7XG4gICAgICAgIHRpY2soZWxhcHNlZCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBEaXNwYXRjaCB0aGUgc3RhcnQgZXZlbnQuXG4gICAgLy8gTm90ZSB0aGlzIG11c3QgYmUgZG9uZSBiZWZvcmUgdGhlIHR3ZWVuIGFyZSBpbml0aWFsaXplZC5cbiAgICBzZWxmLnN0YXRlID0gU1RBUlRJTkc7XG4gICAgc2VsZi5vbi5jYWxsKFwic3RhcnRcIiwgbm9kZSwgbm9kZS5fX2RhdGFfXywgc2VsZi5pbmRleCwgc2VsZi5ncm91cCk7XG4gICAgaWYgKHNlbGYuc3RhdGUgIT09IFNUQVJUSU5HKSByZXR1cm47IC8vIGludGVycnVwdGVkXG4gICAgc2VsZi5zdGF0ZSA9IFNUQVJURUQ7XG5cbiAgICAvLyBJbml0aWFsaXplIHRoZSB0d2VlbiwgZGVsZXRpbmcgbnVsbCB0d2Vlbi5cbiAgICB0d2VlbiA9IG5ldyBBcnJheShuID0gc2VsZi50d2Vlbi5sZW5ndGgpO1xuICAgIGZvciAoaSA9IDAsIGogPSAtMTsgaSA8IG47ICsraSkge1xuICAgICAgaWYgKG8gPSBzZWxmLnR3ZWVuW2ldLnZhbHVlLmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgc2VsZi5pbmRleCwgc2VsZi5ncm91cCkpIHtcbiAgICAgICAgdHdlZW5bKytqXSA9IG87XG4gICAgICB9XG4gICAgfVxuICAgIHR3ZWVuLmxlbmd0aCA9IGogKyAxO1xuICB9XG5cbiAgZnVuY3Rpb24gdGljayhlbGFwc2VkKSB7XG4gICAgdmFyIHQgPSBlbGFwc2VkIDwgc2VsZi5kdXJhdGlvbiA/IHNlbGYuZWFzZS5jYWxsKG51bGwsIGVsYXBzZWQgLyBzZWxmLmR1cmF0aW9uKSA6IChzZWxmLnRpbWVyLnJlc3RhcnQoc3RvcCksIHNlbGYuc3RhdGUgPSBFTkRJTkcsIDEpLFxuICAgICAgICBpID0gLTEsXG4gICAgICAgIG4gPSB0d2Vlbi5sZW5ndGg7XG5cbiAgICB3aGlsZSAoKytpIDwgbikge1xuICAgICAgdHdlZW5baV0uY2FsbChudWxsLCB0KTtcbiAgICB9XG5cbiAgICAvLyBEaXNwYXRjaCB0aGUgZW5kIGV2ZW50LlxuICAgIGlmIChzZWxmLnN0YXRlID09PSBFTkRJTkcpIHtcbiAgICAgIHNlbGYub24uY2FsbChcImVuZFwiLCBub2RlLCBub2RlLl9fZGF0YV9fLCBzZWxmLmluZGV4LCBzZWxmLmdyb3VwKTtcbiAgICAgIHN0b3AoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBzdG9wKCkge1xuICAgIHNlbGYuc3RhdGUgPSBFTkRFRDtcbiAgICBzZWxmLnRpbWVyLnN0b3AoKTtcbiAgICBkZWxldGUgc2NoZWR1bGVzW2lkXTtcbiAgICBmb3IgKHZhciBpIGluIHNjaGVkdWxlcykgcmV0dXJuOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgZGVsZXRlIG5vZGUuX190cmFuc2l0aW9uO1xuICB9XG59XG5cbnZhciBpbnRlcnJ1cHQgPSBmdW5jdGlvbihub2RlLCBuYW1lKSB7XG4gIHZhciBzY2hlZHVsZXMgPSBub2RlLl9fdHJhbnNpdGlvbixcbiAgICAgIHNjaGVkdWxlLFxuICAgICAgYWN0aXZlLFxuICAgICAgZW1wdHkgPSB0cnVlLFxuICAgICAgaTtcblxuICBpZiAoIXNjaGVkdWxlcykgcmV0dXJuO1xuXG4gIG5hbWUgPSBuYW1lID09IG51bGwgPyBudWxsIDogbmFtZSArIFwiXCI7XG5cbiAgZm9yIChpIGluIHNjaGVkdWxlcykge1xuICAgIGlmICgoc2NoZWR1bGUgPSBzY2hlZHVsZXNbaV0pLm5hbWUgIT09IG5hbWUpIHsgZW1wdHkgPSBmYWxzZTsgY29udGludWU7IH1cbiAgICBhY3RpdmUgPSBzY2hlZHVsZS5zdGF0ZSA+IFNUQVJUSU5HICYmIHNjaGVkdWxlLnN0YXRlIDwgRU5ESU5HO1xuICAgIHNjaGVkdWxlLnN0YXRlID0gRU5ERUQ7XG4gICAgc2NoZWR1bGUudGltZXIuc3RvcCgpO1xuICAgIGlmIChhY3RpdmUpIHNjaGVkdWxlLm9uLmNhbGwoXCJpbnRlcnJ1cHRcIiwgbm9kZSwgbm9kZS5fX2RhdGFfXywgc2NoZWR1bGUuaW5kZXgsIHNjaGVkdWxlLmdyb3VwKTtcbiAgICBkZWxldGUgc2NoZWR1bGVzW2ldO1xuICB9XG5cbiAgaWYgKGVtcHR5KSBkZWxldGUgbm9kZS5fX3RyYW5zaXRpb247XG59O1xuXG52YXIgc2VsZWN0aW9uX2ludGVycnVwdCA9IGZ1bmN0aW9uKG5hbWUpIHtcbiAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpIHtcbiAgICBpbnRlcnJ1cHQodGhpcywgbmFtZSk7XG4gIH0pO1xufTtcblxuZnVuY3Rpb24gdHdlZW5SZW1vdmUoaWQsIG5hbWUpIHtcbiAgdmFyIHR3ZWVuMCwgdHdlZW4xO1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHNjaGVkdWxlID0gc2V0KHRoaXMsIGlkKSxcbiAgICAgICAgdHdlZW4gPSBzY2hlZHVsZS50d2VlbjtcblxuICAgIC8vIElmIHRoaXMgbm9kZSBzaGFyZWQgdHdlZW4gd2l0aCB0aGUgcHJldmlvdXMgbm9kZSxcbiAgICAvLyBqdXN0IGFzc2lnbiB0aGUgdXBkYXRlZCBzaGFyZWQgdHdlZW4gYW5kIHdl4oCZcmUgZG9uZSFcbiAgICAvLyBPdGhlcndpc2UsIGNvcHktb24td3JpdGUuXG4gICAgaWYgKHR3ZWVuICE9PSB0d2VlbjApIHtcbiAgICAgIHR3ZWVuMSA9IHR3ZWVuMCA9IHR3ZWVuO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIG4gPSB0d2VlbjEubGVuZ3RoOyBpIDwgbjsgKytpKSB7XG4gICAgICAgIGlmICh0d2VlbjFbaV0ubmFtZSA9PT0gbmFtZSkge1xuICAgICAgICAgIHR3ZWVuMSA9IHR3ZWVuMS5zbGljZSgpO1xuICAgICAgICAgIHR3ZWVuMS5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBzY2hlZHVsZS50d2VlbiA9IHR3ZWVuMTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdHdlZW5GdW5jdGlvbihpZCwgbmFtZSwgdmFsdWUpIHtcbiAgdmFyIHR3ZWVuMCwgdHdlZW4xO1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBFcnJvcjtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciBzY2hlZHVsZSA9IHNldCh0aGlzLCBpZCksXG4gICAgICAgIHR3ZWVuID0gc2NoZWR1bGUudHdlZW47XG5cbiAgICAvLyBJZiB0aGlzIG5vZGUgc2hhcmVkIHR3ZWVuIHdpdGggdGhlIHByZXZpb3VzIG5vZGUsXG4gICAgLy8ganVzdCBhc3NpZ24gdGhlIHVwZGF0ZWQgc2hhcmVkIHR3ZWVuIGFuZCB3ZeKAmXJlIGRvbmUhXG4gICAgLy8gT3RoZXJ3aXNlLCBjb3B5LW9uLXdyaXRlLlxuICAgIGlmICh0d2VlbiAhPT0gdHdlZW4wKSB7XG4gICAgICB0d2VlbjEgPSAodHdlZW4wID0gdHdlZW4pLnNsaWNlKCk7XG4gICAgICBmb3IgKHZhciB0ID0ge25hbWU6IG5hbWUsIHZhbHVlOiB2YWx1ZX0sIGkgPSAwLCBuID0gdHdlZW4xLmxlbmd0aDsgaSA8IG47ICsraSkge1xuICAgICAgICBpZiAodHdlZW4xW2ldLm5hbWUgPT09IG5hbWUpIHtcbiAgICAgICAgICB0d2VlbjFbaV0gPSB0O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaSA9PT0gbikgdHdlZW4xLnB1c2godCk7XG4gICAgfVxuXG4gICAgc2NoZWR1bGUudHdlZW4gPSB0d2VlbjE7XG4gIH07XG59XG5cbnZhciB0cmFuc2l0aW9uX3R3ZWVuID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgdmFyIGlkID0gdGhpcy5faWQ7XG5cbiAgbmFtZSArPSBcIlwiO1xuXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikge1xuICAgIHZhciB0d2VlbiA9IGdldCh0aGlzLm5vZGUoKSwgaWQpLnR3ZWVuO1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gdHdlZW4ubGVuZ3RoLCB0OyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoKHQgPSB0d2VlbltpXSkubmFtZSA9PT0gbmFtZSkge1xuICAgICAgICByZXR1cm4gdC52YWx1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gdGhpcy5lYWNoKCh2YWx1ZSA9PSBudWxsID8gdHdlZW5SZW1vdmUgOiB0d2VlbkZ1bmN0aW9uKShpZCwgbmFtZSwgdmFsdWUpKTtcbn07XG5cbmZ1bmN0aW9uIHR3ZWVuVmFsdWUodHJhbnNpdGlvbiwgbmFtZSwgdmFsdWUpIHtcbiAgdmFyIGlkID0gdHJhbnNpdGlvbi5faWQ7XG5cbiAgdHJhbnNpdGlvbi5lYWNoKGZ1bmN0aW9uKCkge1xuICAgIHZhciBzY2hlZHVsZSA9IHNldCh0aGlzLCBpZCk7XG4gICAgKHNjaGVkdWxlLnZhbHVlIHx8IChzY2hlZHVsZS52YWx1ZSA9IHt9KSlbbmFtZV0gPSB2YWx1ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9KTtcblxuICByZXR1cm4gZnVuY3Rpb24obm9kZSkge1xuICAgIHJldHVybiBnZXQobm9kZSwgaWQpLnZhbHVlW25hbWVdO1xuICB9O1xufVxuXG52YXIgaW50ZXJwb2xhdGUgPSBmdW5jdGlvbihhLCBiKSB7XG4gIHZhciBjO1xuICByZXR1cm4gKHR5cGVvZiBiID09PSBcIm51bWJlclwiID8gZDNJbnRlcnBvbGF0ZS5pbnRlcnBvbGF0ZU51bWJlclxuICAgICAgOiBiIGluc3RhbmNlb2YgZDNDb2xvci5jb2xvciA/IGQzSW50ZXJwb2xhdGUuaW50ZXJwb2xhdGVSZ2JcbiAgICAgIDogKGMgPSBkM0NvbG9yLmNvbG9yKGIpKSA/IChiID0gYywgZDNJbnRlcnBvbGF0ZS5pbnRlcnBvbGF0ZVJnYilcbiAgICAgIDogZDNJbnRlcnBvbGF0ZS5pbnRlcnBvbGF0ZVN0cmluZykoYSwgYik7XG59O1xuXG5mdW5jdGlvbiBhdHRyUmVtb3ZlKG5hbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBhdHRyUmVtb3ZlTlMoZnVsbG5hbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHRoaXMucmVtb3ZlQXR0cmlidXRlTlMoZnVsbG5hbWUuc3BhY2UsIGZ1bGxuYW1lLmxvY2FsKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYXR0ckNvbnN0YW50KG5hbWUsIGludGVycG9sYXRlJCQxLCB2YWx1ZTEpIHtcbiAgdmFyIHZhbHVlMDAsXG4gICAgICBpbnRlcnBvbGF0ZTA7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWUwID0gdGhpcy5nZXRBdHRyaWJ1dGUobmFtZSk7XG4gICAgcmV0dXJuIHZhbHVlMCA9PT0gdmFsdWUxID8gbnVsbFxuICAgICAgICA6IHZhbHVlMCA9PT0gdmFsdWUwMCA/IGludGVycG9sYXRlMFxuICAgICAgICA6IGludGVycG9sYXRlMCA9IGludGVycG9sYXRlJCQxKHZhbHVlMDAgPSB2YWx1ZTAsIHZhbHVlMSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGF0dHJDb25zdGFudE5TKGZ1bGxuYW1lLCBpbnRlcnBvbGF0ZSQkMSwgdmFsdWUxKSB7XG4gIHZhciB2YWx1ZTAwLFxuICAgICAgaW50ZXJwb2xhdGUwO1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZhbHVlMCA9IHRoaXMuZ2V0QXR0cmlidXRlTlMoZnVsbG5hbWUuc3BhY2UsIGZ1bGxuYW1lLmxvY2FsKTtcbiAgICByZXR1cm4gdmFsdWUwID09PSB2YWx1ZTEgPyBudWxsXG4gICAgICAgIDogdmFsdWUwID09PSB2YWx1ZTAwID8gaW50ZXJwb2xhdGUwXG4gICAgICAgIDogaW50ZXJwb2xhdGUwID0gaW50ZXJwb2xhdGUkJDEodmFsdWUwMCA9IHZhbHVlMCwgdmFsdWUxKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gYXR0ckZ1bmN0aW9uKG5hbWUsIGludGVycG9sYXRlJCQxLCB2YWx1ZSkge1xuICB2YXIgdmFsdWUwMCxcbiAgICAgIHZhbHVlMTAsXG4gICAgICBpbnRlcnBvbGF0ZTA7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWUwLCB2YWx1ZTEgPSB2YWx1ZSh0aGlzKTtcbiAgICBpZiAodmFsdWUxID09IG51bGwpIHJldHVybiB2b2lkIHRoaXMucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICAgIHZhbHVlMCA9IHRoaXMuZ2V0QXR0cmlidXRlKG5hbWUpO1xuICAgIHJldHVybiB2YWx1ZTAgPT09IHZhbHVlMSA/IG51bGxcbiAgICAgICAgOiB2YWx1ZTAgPT09IHZhbHVlMDAgJiYgdmFsdWUxID09PSB2YWx1ZTEwID8gaW50ZXJwb2xhdGUwXG4gICAgICAgIDogaW50ZXJwb2xhdGUwID0gaW50ZXJwb2xhdGUkJDEodmFsdWUwMCA9IHZhbHVlMCwgdmFsdWUxMCA9IHZhbHVlMSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGF0dHJGdW5jdGlvbk5TKGZ1bGxuYW1lLCBpbnRlcnBvbGF0ZSQkMSwgdmFsdWUpIHtcbiAgdmFyIHZhbHVlMDAsXG4gICAgICB2YWx1ZTEwLFxuICAgICAgaW50ZXJwb2xhdGUwO1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZhbHVlMCwgdmFsdWUxID0gdmFsdWUodGhpcyk7XG4gICAgaWYgKHZhbHVlMSA9PSBudWxsKSByZXR1cm4gdm9pZCB0aGlzLnJlbW92ZUF0dHJpYnV0ZU5TKGZ1bGxuYW1lLnNwYWNlLCBmdWxsbmFtZS5sb2NhbCk7XG4gICAgdmFsdWUwID0gdGhpcy5nZXRBdHRyaWJ1dGVOUyhmdWxsbmFtZS5zcGFjZSwgZnVsbG5hbWUubG9jYWwpO1xuICAgIHJldHVybiB2YWx1ZTAgPT09IHZhbHVlMSA/IG51bGxcbiAgICAgICAgOiB2YWx1ZTAgPT09IHZhbHVlMDAgJiYgdmFsdWUxID09PSB2YWx1ZTEwID8gaW50ZXJwb2xhdGUwXG4gICAgICAgIDogaW50ZXJwb2xhdGUwID0gaW50ZXJwb2xhdGUkJDEodmFsdWUwMCA9IHZhbHVlMCwgdmFsdWUxMCA9IHZhbHVlMSk7XG4gIH07XG59XG5cbnZhciB0cmFuc2l0aW9uX2F0dHIgPSBmdW5jdGlvbihuYW1lLCB2YWx1ZSkge1xuICB2YXIgZnVsbG5hbWUgPSBkM1NlbGVjdGlvbi5uYW1lc3BhY2UobmFtZSksIGkgPSBmdWxsbmFtZSA9PT0gXCJ0cmFuc2Zvcm1cIiA/IGQzSW50ZXJwb2xhdGUuaW50ZXJwb2xhdGVUcmFuc2Zvcm1TdmcgOiBpbnRlcnBvbGF0ZTtcbiAgcmV0dXJuIHRoaXMuYXR0clR3ZWVuKG5hbWUsIHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICA/IChmdWxsbmFtZS5sb2NhbCA/IGF0dHJGdW5jdGlvbk5TIDogYXR0ckZ1bmN0aW9uKShmdWxsbmFtZSwgaSwgdHdlZW5WYWx1ZSh0aGlzLCBcImF0dHIuXCIgKyBuYW1lLCB2YWx1ZSkpXG4gICAgICA6IHZhbHVlID09IG51bGwgPyAoZnVsbG5hbWUubG9jYWwgPyBhdHRyUmVtb3ZlTlMgOiBhdHRyUmVtb3ZlKShmdWxsbmFtZSlcbiAgICAgIDogKGZ1bGxuYW1lLmxvY2FsID8gYXR0ckNvbnN0YW50TlMgOiBhdHRyQ29uc3RhbnQpKGZ1bGxuYW1lLCBpLCB2YWx1ZSArIFwiXCIpKTtcbn07XG5cbmZ1bmN0aW9uIGF0dHJUd2Vlbk5TKGZ1bGxuYW1lLCB2YWx1ZSkge1xuICBmdW5jdGlvbiB0d2VlbigpIHtcbiAgICB2YXIgbm9kZSA9IHRoaXMsIGkgPSB2YWx1ZS5hcHBseShub2RlLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiBpICYmIGZ1bmN0aW9uKHQpIHtcbiAgICAgIG5vZGUuc2V0QXR0cmlidXRlTlMoZnVsbG5hbWUuc3BhY2UsIGZ1bGxuYW1lLmxvY2FsLCBpKHQpKTtcbiAgICB9O1xuICB9XG4gIHR3ZWVuLl92YWx1ZSA9IHZhbHVlO1xuICByZXR1cm4gdHdlZW47XG59XG5cbmZ1bmN0aW9uIGF0dHJUd2VlbihuYW1lLCB2YWx1ZSkge1xuICBmdW5jdGlvbiB0d2VlbigpIHtcbiAgICB2YXIgbm9kZSA9IHRoaXMsIGkgPSB2YWx1ZS5hcHBseShub2RlLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiBpICYmIGZ1bmN0aW9uKHQpIHtcbiAgICAgIG5vZGUuc2V0QXR0cmlidXRlKG5hbWUsIGkodCkpO1xuICAgIH07XG4gIH1cbiAgdHdlZW4uX3ZhbHVlID0gdmFsdWU7XG4gIHJldHVybiB0d2Vlbjtcbn1cblxudmFyIHRyYW5zaXRpb25fYXR0clR3ZWVuID0gZnVuY3Rpb24obmFtZSwgdmFsdWUpIHtcbiAgdmFyIGtleSA9IFwiYXR0ci5cIiArIG5hbWU7XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMikgcmV0dXJuIChrZXkgPSB0aGlzLnR3ZWVuKGtleSkpICYmIGtleS5fdmFsdWU7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSByZXR1cm4gdGhpcy50d2VlbihrZXksIG51bGwpO1xuICBpZiAodHlwZW9mIHZhbHVlICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBFcnJvcjtcbiAgdmFyIGZ1bGxuYW1lID0gZDNTZWxlY3Rpb24ubmFtZXNwYWNlKG5hbWUpO1xuICByZXR1cm4gdGhpcy50d2VlbihrZXksIChmdWxsbmFtZS5sb2NhbCA/IGF0dHJUd2Vlbk5TIDogYXR0clR3ZWVuKShmdWxsbmFtZSwgdmFsdWUpKTtcbn07XG5cbmZ1bmN0aW9uIGRlbGF5RnVuY3Rpb24oaWQsIHZhbHVlKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICBpbml0KHRoaXMsIGlkKS5kZWxheSA9ICt2YWx1ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBkZWxheUNvbnN0YW50KGlkLCB2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPSArdmFsdWUsIGZ1bmN0aW9uKCkge1xuICAgIGluaXQodGhpcywgaWQpLmRlbGF5ID0gdmFsdWU7XG4gIH07XG59XG5cbnZhciB0cmFuc2l0aW9uX2RlbGF5ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgdmFyIGlkID0gdGhpcy5faWQ7XG5cbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGhcbiAgICAgID8gdGhpcy5lYWNoKCh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgID8gZGVsYXlGdW5jdGlvblxuICAgICAgICAgIDogZGVsYXlDb25zdGFudCkoaWQsIHZhbHVlKSlcbiAgICAgIDogZ2V0KHRoaXMubm9kZSgpLCBpZCkuZGVsYXk7XG59O1xuXG5mdW5jdGlvbiBkdXJhdGlvbkZ1bmN0aW9uKGlkLCB2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgc2V0KHRoaXMsIGlkKS5kdXJhdGlvbiA9ICt2YWx1ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBkdXJhdGlvbkNvbnN0YW50KGlkLCB2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPSArdmFsdWUsIGZ1bmN0aW9uKCkge1xuICAgIHNldCh0aGlzLCBpZCkuZHVyYXRpb24gPSB2YWx1ZTtcbiAgfTtcbn1cblxudmFyIHRyYW5zaXRpb25fZHVyYXRpb24gPSBmdW5jdGlvbih2YWx1ZSkge1xuICB2YXIgaWQgPSB0aGlzLl9pZDtcblxuICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aFxuICAgICAgPyB0aGlzLmVhY2goKHR5cGVvZiB2YWx1ZSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICAgPyBkdXJhdGlvbkZ1bmN0aW9uXG4gICAgICAgICAgOiBkdXJhdGlvbkNvbnN0YW50KShpZCwgdmFsdWUpKVxuICAgICAgOiBnZXQodGhpcy5ub2RlKCksIGlkKS5kdXJhdGlvbjtcbn07XG5cbmZ1bmN0aW9uIGVhc2VDb25zdGFudChpZCwgdmFsdWUpIHtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3I7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICBzZXQodGhpcywgaWQpLmVhc2UgPSB2YWx1ZTtcbiAgfTtcbn1cblxudmFyIHRyYW5zaXRpb25fZWFzZSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHZhciBpZCA9IHRoaXMuX2lkO1xuXG4gIHJldHVybiBhcmd1bWVudHMubGVuZ3RoXG4gICAgICA/IHRoaXMuZWFjaChlYXNlQ29uc3RhbnQoaWQsIHZhbHVlKSlcbiAgICAgIDogZ2V0KHRoaXMubm9kZSgpLCBpZCkuZWFzZTtcbn07XG5cbnZhciB0cmFuc2l0aW9uX2ZpbHRlciA9IGZ1bmN0aW9uKG1hdGNoKSB7XG4gIGlmICh0eXBlb2YgbWF0Y2ggIT09IFwiZnVuY3Rpb25cIikgbWF0Y2ggPSBkM1NlbGVjdGlvbi5tYXRjaGVyKG1hdGNoKTtcblxuICBmb3IgKHZhciBncm91cHMgPSB0aGlzLl9ncm91cHMsIG0gPSBncm91cHMubGVuZ3RoLCBzdWJncm91cHMgPSBuZXcgQXJyYXkobSksIGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIG4gPSBncm91cC5sZW5ndGgsIHN1Ymdyb3VwID0gc3ViZ3JvdXBzW2pdID0gW10sIG5vZGUsIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoKG5vZGUgPSBncm91cFtpXSkgJiYgbWF0Y2guY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBncm91cCkpIHtcbiAgICAgICAgc3ViZ3JvdXAucHVzaChub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3IFRyYW5zaXRpb24oc3ViZ3JvdXBzLCB0aGlzLl9wYXJlbnRzLCB0aGlzLl9uYW1lLCB0aGlzLl9pZCk7XG59O1xuXG52YXIgdHJhbnNpdGlvbl9tZXJnZSA9IGZ1bmN0aW9uKHRyYW5zaXRpb24pIHtcbiAgaWYgKHRyYW5zaXRpb24uX2lkICE9PSB0aGlzLl9pZCkgdGhyb3cgbmV3IEVycm9yO1xuXG4gIGZvciAodmFyIGdyb3VwczAgPSB0aGlzLl9ncm91cHMsIGdyb3VwczEgPSB0cmFuc2l0aW9uLl9ncm91cHMsIG0wID0gZ3JvdXBzMC5sZW5ndGgsIG0xID0gZ3JvdXBzMS5sZW5ndGgsIG0gPSBNYXRoLm1pbihtMCwgbTEpLCBtZXJnZXMgPSBuZXcgQXJyYXkobTApLCBqID0gMDsgaiA8IG07ICsraikge1xuICAgIGZvciAodmFyIGdyb3VwMCA9IGdyb3VwczBbal0sIGdyb3VwMSA9IGdyb3VwczFbal0sIG4gPSBncm91cDAubGVuZ3RoLCBtZXJnZSA9IG1lcmdlc1tqXSA9IG5ldyBBcnJheShuKSwgbm9kZSwgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGlmIChub2RlID0gZ3JvdXAwW2ldIHx8IGdyb3VwMVtpXSkge1xuICAgICAgICBtZXJnZVtpXSA9IG5vZGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZm9yICg7IGogPCBtMDsgKytqKSB7XG4gICAgbWVyZ2VzW2pdID0gZ3JvdXBzMFtqXTtcbiAgfVxuXG4gIHJldHVybiBuZXcgVHJhbnNpdGlvbihtZXJnZXMsIHRoaXMuX3BhcmVudHMsIHRoaXMuX25hbWUsIHRoaXMuX2lkKTtcbn07XG5cbmZ1bmN0aW9uIHN0YXJ0KG5hbWUpIHtcbiAgcmV0dXJuIChuYW1lICsgXCJcIikudHJpbSgpLnNwbGl0KC9efFxccysvKS5ldmVyeShmdW5jdGlvbih0KSB7XG4gICAgdmFyIGkgPSB0LmluZGV4T2YoXCIuXCIpO1xuICAgIGlmIChpID49IDApIHQgPSB0LnNsaWNlKDAsIGkpO1xuICAgIHJldHVybiAhdCB8fCB0ID09PSBcInN0YXJ0XCI7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBvbkZ1bmN0aW9uKGlkLCBuYW1lLCBsaXN0ZW5lcikge1xuICB2YXIgb24wLCBvbjEsIHNpdCA9IHN0YXJ0KG5hbWUpID8gaW5pdCA6IHNldDtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciBzY2hlZHVsZSA9IHNpdCh0aGlzLCBpZCksXG4gICAgICAgIG9uID0gc2NoZWR1bGUub247XG5cbiAgICAvLyBJZiB0aGlzIG5vZGUgc2hhcmVkIGEgZGlzcGF0Y2ggd2l0aCB0aGUgcHJldmlvdXMgbm9kZSxcbiAgICAvLyBqdXN0IGFzc2lnbiB0aGUgdXBkYXRlZCBzaGFyZWQgZGlzcGF0Y2ggYW5kIHdl4oCZcmUgZG9uZSFcbiAgICAvLyBPdGhlcndpc2UsIGNvcHktb24td3JpdGUuXG4gICAgaWYgKG9uICE9PSBvbjApIChvbjEgPSAob24wID0gb24pLmNvcHkoKSkub24obmFtZSwgbGlzdGVuZXIpO1xuXG4gICAgc2NoZWR1bGUub24gPSBvbjE7XG4gIH07XG59XG5cbnZhciB0cmFuc2l0aW9uX29uID0gZnVuY3Rpb24obmFtZSwgbGlzdGVuZXIpIHtcbiAgdmFyIGlkID0gdGhpcy5faWQ7XG5cbiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPCAyXG4gICAgICA/IGdldCh0aGlzLm5vZGUoKSwgaWQpLm9uLm9uKG5hbWUpXG4gICAgICA6IHRoaXMuZWFjaChvbkZ1bmN0aW9uKGlkLCBuYW1lLCBsaXN0ZW5lcikpO1xufTtcblxuZnVuY3Rpb24gcmVtb3ZlRnVuY3Rpb24oaWQpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciBwYXJlbnQgPSB0aGlzLnBhcmVudE5vZGU7XG4gICAgZm9yICh2YXIgaSBpbiB0aGlzLl9fdHJhbnNpdGlvbikgaWYgKCtpICE9PSBpZCkgcmV0dXJuO1xuICAgIGlmIChwYXJlbnQpIHBhcmVudC5yZW1vdmVDaGlsZCh0aGlzKTtcbiAgfTtcbn1cblxudmFyIHRyYW5zaXRpb25fcmVtb3ZlID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLm9uKFwiZW5kLnJlbW92ZVwiLCByZW1vdmVGdW5jdGlvbih0aGlzLl9pZCkpO1xufTtcblxudmFyIHRyYW5zaXRpb25fc2VsZWN0ID0gZnVuY3Rpb24oc2VsZWN0KSB7XG4gIHZhciBuYW1lID0gdGhpcy5fbmFtZSxcbiAgICAgIGlkID0gdGhpcy5faWQ7XG5cbiAgaWYgKHR5cGVvZiBzZWxlY3QgIT09IFwiZnVuY3Rpb25cIikgc2VsZWN0ID0gZDNTZWxlY3Rpb24uc2VsZWN0b3Ioc2VsZWN0KTtcblxuICBmb3IgKHZhciBncm91cHMgPSB0aGlzLl9ncm91cHMsIG0gPSBncm91cHMubGVuZ3RoLCBzdWJncm91cHMgPSBuZXcgQXJyYXkobSksIGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIG4gPSBncm91cC5sZW5ndGgsIHN1Ymdyb3VwID0gc3ViZ3JvdXBzW2pdID0gbmV3IEFycmF5KG4pLCBub2RlLCBzdWJub2RlLCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgaWYgKChub2RlID0gZ3JvdXBbaV0pICYmIChzdWJub2RlID0gc2VsZWN0LmNhbGwobm9kZSwgbm9kZS5fX2RhdGFfXywgaSwgZ3JvdXApKSkge1xuICAgICAgICBpZiAoXCJfX2RhdGFfX1wiIGluIG5vZGUpIHN1Ym5vZGUuX19kYXRhX18gPSBub2RlLl9fZGF0YV9fO1xuICAgICAgICBzdWJncm91cFtpXSA9IHN1Ym5vZGU7XG4gICAgICAgIHNjaGVkdWxlKHN1Ymdyb3VwW2ldLCBuYW1lLCBpZCwgaSwgc3ViZ3JvdXAsIGdldChub2RlLCBpZCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHJhbnNpdGlvbihzdWJncm91cHMsIHRoaXMuX3BhcmVudHMsIG5hbWUsIGlkKTtcbn07XG5cbnZhciB0cmFuc2l0aW9uX3NlbGVjdEFsbCA9IGZ1bmN0aW9uKHNlbGVjdCkge1xuICB2YXIgbmFtZSA9IHRoaXMuX25hbWUsXG4gICAgICBpZCA9IHRoaXMuX2lkO1xuXG4gIGlmICh0eXBlb2Ygc2VsZWN0ICE9PSBcImZ1bmN0aW9uXCIpIHNlbGVjdCA9IGQzU2VsZWN0aW9uLnNlbGVjdG9yQWxsKHNlbGVjdCk7XG5cbiAgZm9yICh2YXIgZ3JvdXBzID0gdGhpcy5fZ3JvdXBzLCBtID0gZ3JvdXBzLmxlbmd0aCwgc3ViZ3JvdXBzID0gW10sIHBhcmVudHMgPSBbXSwgaiA9IDA7IGogPCBtOyArK2opIHtcbiAgICBmb3IgKHZhciBncm91cCA9IGdyb3Vwc1tqXSwgbiA9IGdyb3VwLmxlbmd0aCwgbm9kZSwgaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIGlmIChub2RlID0gZ3JvdXBbaV0pIHtcbiAgICAgICAgZm9yICh2YXIgY2hpbGRyZW4gPSBzZWxlY3QuY2FsbChub2RlLCBub2RlLl9fZGF0YV9fLCBpLCBncm91cCksIGNoaWxkLCBpbmhlcml0ID0gZ2V0KG5vZGUsIGlkKSwgayA9IDAsIGwgPSBjaGlsZHJlbi5sZW5ndGg7IGsgPCBsOyArK2spIHtcbiAgICAgICAgICBpZiAoY2hpbGQgPSBjaGlsZHJlbltrXSkge1xuICAgICAgICAgICAgc2NoZWR1bGUoY2hpbGQsIG5hbWUsIGlkLCBrLCBjaGlsZHJlbiwgaW5oZXJpdCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHN1Ymdyb3Vwcy5wdXNoKGNoaWxkcmVuKTtcbiAgICAgICAgcGFyZW50cy5wdXNoKG5vZGUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHJhbnNpdGlvbihzdWJncm91cHMsIHBhcmVudHMsIG5hbWUsIGlkKTtcbn07XG5cbnZhciBTZWxlY3Rpb24gPSBkM1NlbGVjdGlvbi5zZWxlY3Rpb24ucHJvdG90eXBlLmNvbnN0cnVjdG9yO1xuXG52YXIgdHJhbnNpdGlvbl9zZWxlY3Rpb24gPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIG5ldyBTZWxlY3Rpb24odGhpcy5fZ3JvdXBzLCB0aGlzLl9wYXJlbnRzKTtcbn07XG5cbmZ1bmN0aW9uIHN0eWxlUmVtb3ZlKG5hbWUsIGludGVycG9sYXRlJCQxKSB7XG4gIHZhciB2YWx1ZTAwLFxuICAgICAgdmFsdWUxMCxcbiAgICAgIGludGVycG9sYXRlMDtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciB2YWx1ZTAgPSBkM1NlbGVjdGlvbi5zdHlsZSh0aGlzLCBuYW1lKSxcbiAgICAgICAgdmFsdWUxID0gKHRoaXMuc3R5bGUucmVtb3ZlUHJvcGVydHkobmFtZSksIGQzU2VsZWN0aW9uLnN0eWxlKHRoaXMsIG5hbWUpKTtcbiAgICByZXR1cm4gdmFsdWUwID09PSB2YWx1ZTEgPyBudWxsXG4gICAgICAgIDogdmFsdWUwID09PSB2YWx1ZTAwICYmIHZhbHVlMSA9PT0gdmFsdWUxMCA/IGludGVycG9sYXRlMFxuICAgICAgICA6IGludGVycG9sYXRlMCA9IGludGVycG9sYXRlJCQxKHZhbHVlMDAgPSB2YWx1ZTAsIHZhbHVlMTAgPSB2YWx1ZTEpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBzdHlsZVJlbW92ZUVuZChuYW1lKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnN0eWxlLnJlbW92ZVByb3BlcnR5KG5hbWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBzdHlsZUNvbnN0YW50KG5hbWUsIGludGVycG9sYXRlJCQxLCB2YWx1ZTEpIHtcbiAgdmFyIHZhbHVlMDAsXG4gICAgICBpbnRlcnBvbGF0ZTA7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdmFsdWUwID0gZDNTZWxlY3Rpb24uc3R5bGUodGhpcywgbmFtZSk7XG4gICAgcmV0dXJuIHZhbHVlMCA9PT0gdmFsdWUxID8gbnVsbFxuICAgICAgICA6IHZhbHVlMCA9PT0gdmFsdWUwMCA/IGludGVycG9sYXRlMFxuICAgICAgICA6IGludGVycG9sYXRlMCA9IGludGVycG9sYXRlJCQxKHZhbHVlMDAgPSB2YWx1ZTAsIHZhbHVlMSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHN0eWxlRnVuY3Rpb24obmFtZSwgaW50ZXJwb2xhdGUkJDEsIHZhbHVlKSB7XG4gIHZhciB2YWx1ZTAwLFxuICAgICAgdmFsdWUxMCxcbiAgICAgIGludGVycG9sYXRlMDtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciB2YWx1ZTAgPSBkM1NlbGVjdGlvbi5zdHlsZSh0aGlzLCBuYW1lKSxcbiAgICAgICAgdmFsdWUxID0gdmFsdWUodGhpcyk7XG4gICAgaWYgKHZhbHVlMSA9PSBudWxsKSB2YWx1ZTEgPSAodGhpcy5zdHlsZS5yZW1vdmVQcm9wZXJ0eShuYW1lKSwgZDNTZWxlY3Rpb24uc3R5bGUodGhpcywgbmFtZSkpO1xuICAgIHJldHVybiB2YWx1ZTAgPT09IHZhbHVlMSA/IG51bGxcbiAgICAgICAgOiB2YWx1ZTAgPT09IHZhbHVlMDAgJiYgdmFsdWUxID09PSB2YWx1ZTEwID8gaW50ZXJwb2xhdGUwXG4gICAgICAgIDogaW50ZXJwb2xhdGUwID0gaW50ZXJwb2xhdGUkJDEodmFsdWUwMCA9IHZhbHVlMCwgdmFsdWUxMCA9IHZhbHVlMSk7XG4gIH07XG59XG5cbnZhciB0cmFuc2l0aW9uX3N0eWxlID0gZnVuY3Rpb24obmFtZSwgdmFsdWUsIHByaW9yaXR5KSB7XG4gIHZhciBpID0gKG5hbWUgKz0gXCJcIikgPT09IFwidHJhbnNmb3JtXCIgPyBkM0ludGVycG9sYXRlLmludGVycG9sYXRlVHJhbnNmb3JtQ3NzIDogaW50ZXJwb2xhdGU7XG4gIHJldHVybiB2YWx1ZSA9PSBudWxsID8gdGhpc1xuICAgICAgICAgIC5zdHlsZVR3ZWVuKG5hbWUsIHN0eWxlUmVtb3ZlKG5hbWUsIGkpKVxuICAgICAgICAgIC5vbihcImVuZC5zdHlsZS5cIiArIG5hbWUsIHN0eWxlUmVtb3ZlRW5kKG5hbWUpKVxuICAgICAgOiB0aGlzLnN0eWxlVHdlZW4obmFtZSwgdHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICA/IHN0eWxlRnVuY3Rpb24obmFtZSwgaSwgdHdlZW5WYWx1ZSh0aGlzLCBcInN0eWxlLlwiICsgbmFtZSwgdmFsdWUpKVxuICAgICAgICAgIDogc3R5bGVDb25zdGFudChuYW1lLCBpLCB2YWx1ZSArIFwiXCIpLCBwcmlvcml0eSk7XG59O1xuXG5mdW5jdGlvbiBzdHlsZVR3ZWVuKG5hbWUsIHZhbHVlLCBwcmlvcml0eSkge1xuICBmdW5jdGlvbiB0d2VlbigpIHtcbiAgICB2YXIgbm9kZSA9IHRoaXMsIGkgPSB2YWx1ZS5hcHBseShub2RlLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiBpICYmIGZ1bmN0aW9uKHQpIHtcbiAgICAgIG5vZGUuc3R5bGUuc2V0UHJvcGVydHkobmFtZSwgaSh0KSwgcHJpb3JpdHkpO1xuICAgIH07XG4gIH1cbiAgdHdlZW4uX3ZhbHVlID0gdmFsdWU7XG4gIHJldHVybiB0d2Vlbjtcbn1cblxudmFyIHRyYW5zaXRpb25fc3R5bGVUd2VlbiA9IGZ1bmN0aW9uKG5hbWUsIHZhbHVlLCBwcmlvcml0eSkge1xuICB2YXIga2V5ID0gXCJzdHlsZS5cIiArIChuYW1lICs9IFwiXCIpO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHJldHVybiAoa2V5ID0gdGhpcy50d2VlbihrZXkpKSAmJiBrZXkuX3ZhbHVlO1xuICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuIHRoaXMudHdlZW4oa2V5LCBudWxsKTtcbiAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJmdW5jdGlvblwiKSB0aHJvdyBuZXcgRXJyb3I7XG4gIHJldHVybiB0aGlzLnR3ZWVuKGtleSwgc3R5bGVUd2VlbihuYW1lLCB2YWx1ZSwgcHJpb3JpdHkgPT0gbnVsbCA/IFwiXCIgOiBwcmlvcml0eSkpO1xufTtcblxuZnVuY3Rpb24gdGV4dENvbnN0YW50KHZhbHVlKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnRleHRDb250ZW50ID0gdmFsdWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHRleHRGdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZhbHVlMSA9IHZhbHVlKHRoaXMpO1xuICAgIHRoaXMudGV4dENvbnRlbnQgPSB2YWx1ZTEgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZTE7XG4gIH07XG59XG5cbnZhciB0cmFuc2l0aW9uX3RleHQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gdGhpcy50d2VlbihcInRleHRcIiwgdHlwZW9mIHZhbHVlID09PSBcImZ1bmN0aW9uXCJcbiAgICAgID8gdGV4dEZ1bmN0aW9uKHR3ZWVuVmFsdWUodGhpcywgXCJ0ZXh0XCIsIHZhbHVlKSlcbiAgICAgIDogdGV4dENvbnN0YW50KHZhbHVlID09IG51bGwgPyBcIlwiIDogdmFsdWUgKyBcIlwiKSk7XG59O1xuXG52YXIgdHJhbnNpdGlvbl90cmFuc2l0aW9uID0gZnVuY3Rpb24oKSB7XG4gIHZhciBuYW1lID0gdGhpcy5fbmFtZSxcbiAgICAgIGlkMCA9IHRoaXMuX2lkLFxuICAgICAgaWQxID0gbmV3SWQoKTtcblxuICBmb3IgKHZhciBncm91cHMgPSB0aGlzLl9ncm91cHMsIG0gPSBncm91cHMubGVuZ3RoLCBqID0gMDsgaiA8IG07ICsraikge1xuICAgIGZvciAodmFyIGdyb3VwID0gZ3JvdXBzW2pdLCBuID0gZ3JvdXAubGVuZ3RoLCBub2RlLCBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgaWYgKG5vZGUgPSBncm91cFtpXSkge1xuICAgICAgICB2YXIgaW5oZXJpdCA9IGdldChub2RlLCBpZDApO1xuICAgICAgICBzY2hlZHVsZShub2RlLCBuYW1lLCBpZDEsIGksIGdyb3VwLCB7XG4gICAgICAgICAgdGltZTogaW5oZXJpdC50aW1lICsgaW5oZXJpdC5kZWxheSArIGluaGVyaXQuZHVyYXRpb24sXG4gICAgICAgICAgZGVsYXk6IDAsXG4gICAgICAgICAgZHVyYXRpb246IGluaGVyaXQuZHVyYXRpb24sXG4gICAgICAgICAgZWFzZTogaW5oZXJpdC5lYXNlXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHJhbnNpdGlvbihncm91cHMsIHRoaXMuX3BhcmVudHMsIG5hbWUsIGlkMSk7XG59O1xuXG52YXIgaWQgPSAwO1xuXG5mdW5jdGlvbiBUcmFuc2l0aW9uKGdyb3VwcywgcGFyZW50cywgbmFtZSwgaWQpIHtcbiAgdGhpcy5fZ3JvdXBzID0gZ3JvdXBzO1xuICB0aGlzLl9wYXJlbnRzID0gcGFyZW50cztcbiAgdGhpcy5fbmFtZSA9IG5hbWU7XG4gIHRoaXMuX2lkID0gaWQ7XG59XG5cbmZ1bmN0aW9uIHRyYW5zaXRpb24obmFtZSkge1xuICByZXR1cm4gZDNTZWxlY3Rpb24uc2VsZWN0aW9uKCkudHJhbnNpdGlvbihuYW1lKTtcbn1cblxuZnVuY3Rpb24gbmV3SWQoKSB7XG4gIHJldHVybiArK2lkO1xufVxuXG52YXIgc2VsZWN0aW9uX3Byb3RvdHlwZSA9IGQzU2VsZWN0aW9uLnNlbGVjdGlvbi5wcm90b3R5cGU7XG5cblRyYW5zaXRpb24ucHJvdG90eXBlID0gdHJhbnNpdGlvbi5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBUcmFuc2l0aW9uLFxuICBzZWxlY3Q6IHRyYW5zaXRpb25fc2VsZWN0LFxuICBzZWxlY3RBbGw6IHRyYW5zaXRpb25fc2VsZWN0QWxsLFxuICBmaWx0ZXI6IHRyYW5zaXRpb25fZmlsdGVyLFxuICBtZXJnZTogdHJhbnNpdGlvbl9tZXJnZSxcbiAgc2VsZWN0aW9uOiB0cmFuc2l0aW9uX3NlbGVjdGlvbixcbiAgdHJhbnNpdGlvbjogdHJhbnNpdGlvbl90cmFuc2l0aW9uLFxuICBjYWxsOiBzZWxlY3Rpb25fcHJvdG90eXBlLmNhbGwsXG4gIG5vZGVzOiBzZWxlY3Rpb25fcHJvdG90eXBlLm5vZGVzLFxuICBub2RlOiBzZWxlY3Rpb25fcHJvdG90eXBlLm5vZGUsXG4gIHNpemU6IHNlbGVjdGlvbl9wcm90b3R5cGUuc2l6ZSxcbiAgZW1wdHk6IHNlbGVjdGlvbl9wcm90b3R5cGUuZW1wdHksXG4gIGVhY2g6IHNlbGVjdGlvbl9wcm90b3R5cGUuZWFjaCxcbiAgb246IHRyYW5zaXRpb25fb24sXG4gIGF0dHI6IHRyYW5zaXRpb25fYXR0cixcbiAgYXR0clR3ZWVuOiB0cmFuc2l0aW9uX2F0dHJUd2VlbixcbiAgc3R5bGU6IHRyYW5zaXRpb25fc3R5bGUsXG4gIHN0eWxlVHdlZW46IHRyYW5zaXRpb25fc3R5bGVUd2VlbixcbiAgdGV4dDogdHJhbnNpdGlvbl90ZXh0LFxuICByZW1vdmU6IHRyYW5zaXRpb25fcmVtb3ZlLFxuICB0d2VlbjogdHJhbnNpdGlvbl90d2VlbixcbiAgZGVsYXk6IHRyYW5zaXRpb25fZGVsYXksXG4gIGR1cmF0aW9uOiB0cmFuc2l0aW9uX2R1cmF0aW9uLFxuICBlYXNlOiB0cmFuc2l0aW9uX2Vhc2Vcbn07XG5cbnZhciBkZWZhdWx0VGltaW5nID0ge1xuICB0aW1lOiBudWxsLCAvLyBTZXQgb24gdXNlLlxuICBkZWxheTogMCxcbiAgZHVyYXRpb246IDI1MCxcbiAgZWFzZTogZDNFYXNlLmVhc2VDdWJpY0luT3V0XG59O1xuXG5mdW5jdGlvbiBpbmhlcml0KG5vZGUsIGlkKSB7XG4gIHZhciB0aW1pbmc7XG4gIHdoaWxlICghKHRpbWluZyA9IG5vZGUuX190cmFuc2l0aW9uKSB8fCAhKHRpbWluZyA9IHRpbWluZ1tpZF0pKSB7XG4gICAgaWYgKCEobm9kZSA9IG5vZGUucGFyZW50Tm9kZSkpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0VGltaW5nLnRpbWUgPSBkM1RpbWVyLm5vdygpLCBkZWZhdWx0VGltaW5nO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdGltaW5nO1xufVxuXG52YXIgc2VsZWN0aW9uX3RyYW5zaXRpb24gPSBmdW5jdGlvbihuYW1lKSB7XG4gIHZhciBpZCxcbiAgICAgIHRpbWluZztcblxuICBpZiAobmFtZSBpbnN0YW5jZW9mIFRyYW5zaXRpb24pIHtcbiAgICBpZCA9IG5hbWUuX2lkLCBuYW1lID0gbmFtZS5fbmFtZTtcbiAgfSBlbHNlIHtcbiAgICBpZCA9IG5ld0lkKCksICh0aW1pbmcgPSBkZWZhdWx0VGltaW5nKS50aW1lID0gZDNUaW1lci5ub3coKSwgbmFtZSA9IG5hbWUgPT0gbnVsbCA/IG51bGwgOiBuYW1lICsgXCJcIjtcbiAgfVxuXG4gIGZvciAodmFyIGdyb3VwcyA9IHRoaXMuX2dyb3VwcywgbSA9IGdyb3Vwcy5sZW5ndGgsIGogPSAwOyBqIDwgbTsgKytqKSB7XG4gICAgZm9yICh2YXIgZ3JvdXAgPSBncm91cHNbal0sIG4gPSBncm91cC5sZW5ndGgsIG5vZGUsIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAobm9kZSA9IGdyb3VwW2ldKSB7XG4gICAgICAgIHNjaGVkdWxlKG5vZGUsIG5hbWUsIGlkLCBpLCBncm91cCwgdGltaW5nIHx8IGluaGVyaXQobm9kZSwgaWQpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3IFRyYW5zaXRpb24oZ3JvdXBzLCB0aGlzLl9wYXJlbnRzLCBuYW1lLCBpZCk7XG59O1xuXG5kM1NlbGVjdGlvbi5zZWxlY3Rpb24ucHJvdG90eXBlLmludGVycnVwdCA9IHNlbGVjdGlvbl9pbnRlcnJ1cHQ7XG5kM1NlbGVjdGlvbi5zZWxlY3Rpb24ucHJvdG90eXBlLnRyYW5zaXRpb24gPSBzZWxlY3Rpb25fdHJhbnNpdGlvbjtcblxudmFyIHJvb3QgPSBbbnVsbF07XG5cbnZhciBhY3RpdmUgPSBmdW5jdGlvbihub2RlLCBuYW1lKSB7XG4gIHZhciBzY2hlZHVsZXMgPSBub2RlLl9fdHJhbnNpdGlvbixcbiAgICAgIHNjaGVkdWxlLFxuICAgICAgaTtcblxuICBpZiAoc2NoZWR1bGVzKSB7XG4gICAgbmFtZSA9IG5hbWUgPT0gbnVsbCA/IG51bGwgOiBuYW1lICsgXCJcIjtcbiAgICBmb3IgKGkgaW4gc2NoZWR1bGVzKSB7XG4gICAgICBpZiAoKHNjaGVkdWxlID0gc2NoZWR1bGVzW2ldKS5zdGF0ZSA+IFNDSEVEVUxFRCAmJiBzY2hlZHVsZS5uYW1lID09PSBuYW1lKSB7XG4gICAgICAgIHJldHVybiBuZXcgVHJhbnNpdGlvbihbW25vZGVdXSwgcm9vdCwgbmFtZSwgK2kpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufTtcblxuZXhwb3J0cy50cmFuc2l0aW9uID0gdHJhbnNpdGlvbjtcbmV4cG9ydHMuYWN0aXZlID0gYWN0aXZlO1xuZXhwb3J0cy5pbnRlcnJ1cHQgPSBpbnRlcnJ1cHQ7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG5cbn0pKSk7XG4iLCIvLyBodHRwczovL2QzanMub3JnL2QzLXZvcm9ub2kvIFZlcnNpb24gMS4xLjIuIENvcHlyaWdodCAyMDE3IE1pa2UgQm9zdG9jay5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG5cdHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5kMyA9IGdsb2JhbC5kMyB8fCB7fSkpKTtcbn0odGhpcywgKGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxudmFyIGNvbnN0YW50ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHg7XG4gIH07XG59O1xuXG5mdW5jdGlvbiB4KGQpIHtcbiAgcmV0dXJuIGRbMF07XG59XG5cbmZ1bmN0aW9uIHkoZCkge1xuICByZXR1cm4gZFsxXTtcbn1cblxuZnVuY3Rpb24gUmVkQmxhY2tUcmVlKCkge1xuICB0aGlzLl8gPSBudWxsOyAvLyByb290IG5vZGVcbn1cblxuZnVuY3Rpb24gUmVkQmxhY2tOb2RlKG5vZGUpIHtcbiAgbm9kZS5VID0gLy8gcGFyZW50IG5vZGVcbiAgbm9kZS5DID0gLy8gY29sb3IgLSB0cnVlIGZvciByZWQsIGZhbHNlIGZvciBibGFja1xuICBub2RlLkwgPSAvLyBsZWZ0IG5vZGVcbiAgbm9kZS5SID0gLy8gcmlnaHQgbm9kZVxuICBub2RlLlAgPSAvLyBwcmV2aW91cyBub2RlXG4gIG5vZGUuTiA9IG51bGw7IC8vIG5leHQgbm9kZVxufVxuXG5SZWRCbGFja1RyZWUucHJvdG90eXBlID0ge1xuICBjb25zdHJ1Y3RvcjogUmVkQmxhY2tUcmVlLFxuXG4gIGluc2VydDogZnVuY3Rpb24oYWZ0ZXIsIG5vZGUpIHtcbiAgICB2YXIgcGFyZW50LCBncmFuZHBhLCB1bmNsZTtcblxuICAgIGlmIChhZnRlcikge1xuICAgICAgbm9kZS5QID0gYWZ0ZXI7XG4gICAgICBub2RlLk4gPSBhZnRlci5OO1xuICAgICAgaWYgKGFmdGVyLk4pIGFmdGVyLk4uUCA9IG5vZGU7XG4gICAgICBhZnRlci5OID0gbm9kZTtcbiAgICAgIGlmIChhZnRlci5SKSB7XG4gICAgICAgIGFmdGVyID0gYWZ0ZXIuUjtcbiAgICAgICAgd2hpbGUgKGFmdGVyLkwpIGFmdGVyID0gYWZ0ZXIuTDtcbiAgICAgICAgYWZ0ZXIuTCA9IG5vZGU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhZnRlci5SID0gbm9kZTtcbiAgICAgIH1cbiAgICAgIHBhcmVudCA9IGFmdGVyO1xuICAgIH0gZWxzZSBpZiAodGhpcy5fKSB7XG4gICAgICBhZnRlciA9IFJlZEJsYWNrRmlyc3QodGhpcy5fKTtcbiAgICAgIG5vZGUuUCA9IG51bGw7XG4gICAgICBub2RlLk4gPSBhZnRlcjtcbiAgICAgIGFmdGVyLlAgPSBhZnRlci5MID0gbm9kZTtcbiAgICAgIHBhcmVudCA9IGFmdGVyO1xuICAgIH0gZWxzZSB7XG4gICAgICBub2RlLlAgPSBub2RlLk4gPSBudWxsO1xuICAgICAgdGhpcy5fID0gbm9kZTtcbiAgICAgIHBhcmVudCA9IG51bGw7XG4gICAgfVxuICAgIG5vZGUuTCA9IG5vZGUuUiA9IG51bGw7XG4gICAgbm9kZS5VID0gcGFyZW50O1xuICAgIG5vZGUuQyA9IHRydWU7XG5cbiAgICBhZnRlciA9IG5vZGU7XG4gICAgd2hpbGUgKHBhcmVudCAmJiBwYXJlbnQuQykge1xuICAgICAgZ3JhbmRwYSA9IHBhcmVudC5VO1xuICAgICAgaWYgKHBhcmVudCA9PT0gZ3JhbmRwYS5MKSB7XG4gICAgICAgIHVuY2xlID0gZ3JhbmRwYS5SO1xuICAgICAgICBpZiAodW5jbGUgJiYgdW5jbGUuQykge1xuICAgICAgICAgIHBhcmVudC5DID0gdW5jbGUuQyA9IGZhbHNlO1xuICAgICAgICAgIGdyYW5kcGEuQyA9IHRydWU7XG4gICAgICAgICAgYWZ0ZXIgPSBncmFuZHBhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChhZnRlciA9PT0gcGFyZW50LlIpIHtcbiAgICAgICAgICAgIFJlZEJsYWNrUm90YXRlTGVmdCh0aGlzLCBwYXJlbnQpO1xuICAgICAgICAgICAgYWZ0ZXIgPSBwYXJlbnQ7XG4gICAgICAgICAgICBwYXJlbnQgPSBhZnRlci5VO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwYXJlbnQuQyA9IGZhbHNlO1xuICAgICAgICAgIGdyYW5kcGEuQyA9IHRydWU7XG4gICAgICAgICAgUmVkQmxhY2tSb3RhdGVSaWdodCh0aGlzLCBncmFuZHBhKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdW5jbGUgPSBncmFuZHBhLkw7XG4gICAgICAgIGlmICh1bmNsZSAmJiB1bmNsZS5DKSB7XG4gICAgICAgICAgcGFyZW50LkMgPSB1bmNsZS5DID0gZmFsc2U7XG4gICAgICAgICAgZ3JhbmRwYS5DID0gdHJ1ZTtcbiAgICAgICAgICBhZnRlciA9IGdyYW5kcGE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGFmdGVyID09PSBwYXJlbnQuTCkge1xuICAgICAgICAgICAgUmVkQmxhY2tSb3RhdGVSaWdodCh0aGlzLCBwYXJlbnQpO1xuICAgICAgICAgICAgYWZ0ZXIgPSBwYXJlbnQ7XG4gICAgICAgICAgICBwYXJlbnQgPSBhZnRlci5VO1xuICAgICAgICAgIH1cbiAgICAgICAgICBwYXJlbnQuQyA9IGZhbHNlO1xuICAgICAgICAgIGdyYW5kcGEuQyA9IHRydWU7XG4gICAgICAgICAgUmVkQmxhY2tSb3RhdGVMZWZ0KHRoaXMsIGdyYW5kcGEpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBwYXJlbnQgPSBhZnRlci5VO1xuICAgIH1cbiAgICB0aGlzLl8uQyA9IGZhbHNlO1xuICB9LFxuXG4gIHJlbW92ZTogZnVuY3Rpb24obm9kZSkge1xuICAgIGlmIChub2RlLk4pIG5vZGUuTi5QID0gbm9kZS5QO1xuICAgIGlmIChub2RlLlApIG5vZGUuUC5OID0gbm9kZS5OO1xuICAgIG5vZGUuTiA9IG5vZGUuUCA9IG51bGw7XG5cbiAgICB2YXIgcGFyZW50ID0gbm9kZS5VLFxuICAgICAgICBzaWJsaW5nLFxuICAgICAgICBsZWZ0ID0gbm9kZS5MLFxuICAgICAgICByaWdodCA9IG5vZGUuUixcbiAgICAgICAgbmV4dCxcbiAgICAgICAgcmVkO1xuXG4gICAgaWYgKCFsZWZ0KSBuZXh0ID0gcmlnaHQ7XG4gICAgZWxzZSBpZiAoIXJpZ2h0KSBuZXh0ID0gbGVmdDtcbiAgICBlbHNlIG5leHQgPSBSZWRCbGFja0ZpcnN0KHJpZ2h0KTtcblxuICAgIGlmIChwYXJlbnQpIHtcbiAgICAgIGlmIChwYXJlbnQuTCA9PT0gbm9kZSkgcGFyZW50LkwgPSBuZXh0O1xuICAgICAgZWxzZSBwYXJlbnQuUiA9IG5leHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuXyA9IG5leHQ7XG4gICAgfVxuXG4gICAgaWYgKGxlZnQgJiYgcmlnaHQpIHtcbiAgICAgIHJlZCA9IG5leHQuQztcbiAgICAgIG5leHQuQyA9IG5vZGUuQztcbiAgICAgIG5leHQuTCA9IGxlZnQ7XG4gICAgICBsZWZ0LlUgPSBuZXh0O1xuICAgICAgaWYgKG5leHQgIT09IHJpZ2h0KSB7XG4gICAgICAgIHBhcmVudCA9IG5leHQuVTtcbiAgICAgICAgbmV4dC5VID0gbm9kZS5VO1xuICAgICAgICBub2RlID0gbmV4dC5SO1xuICAgICAgICBwYXJlbnQuTCA9IG5vZGU7XG4gICAgICAgIG5leHQuUiA9IHJpZ2h0O1xuICAgICAgICByaWdodC5VID0gbmV4dDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5leHQuVSA9IHBhcmVudDtcbiAgICAgICAgcGFyZW50ID0gbmV4dDtcbiAgICAgICAgbm9kZSA9IG5leHQuUjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmVkID0gbm9kZS5DO1xuICAgICAgbm9kZSA9IG5leHQ7XG4gICAgfVxuXG4gICAgaWYgKG5vZGUpIG5vZGUuVSA9IHBhcmVudDtcbiAgICBpZiAocmVkKSByZXR1cm47XG4gICAgaWYgKG5vZGUgJiYgbm9kZS5DKSB7IG5vZGUuQyA9IGZhbHNlOyByZXR1cm47IH1cblxuICAgIGRvIHtcbiAgICAgIGlmIChub2RlID09PSB0aGlzLl8pIGJyZWFrO1xuICAgICAgaWYgKG5vZGUgPT09IHBhcmVudC5MKSB7XG4gICAgICAgIHNpYmxpbmcgPSBwYXJlbnQuUjtcbiAgICAgICAgaWYgKHNpYmxpbmcuQykge1xuICAgICAgICAgIHNpYmxpbmcuQyA9IGZhbHNlO1xuICAgICAgICAgIHBhcmVudC5DID0gdHJ1ZTtcbiAgICAgICAgICBSZWRCbGFja1JvdGF0ZUxlZnQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICBzaWJsaW5nID0gcGFyZW50LlI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChzaWJsaW5nLkwgJiYgc2libGluZy5MLkMpXG4gICAgICAgICAgICB8fCAoc2libGluZy5SICYmIHNpYmxpbmcuUi5DKSkge1xuICAgICAgICAgIGlmICghc2libGluZy5SIHx8ICFzaWJsaW5nLlIuQykge1xuICAgICAgICAgICAgc2libGluZy5MLkMgPSBmYWxzZTtcbiAgICAgICAgICAgIHNpYmxpbmcuQyA9IHRydWU7XG4gICAgICAgICAgICBSZWRCbGFja1JvdGF0ZVJpZ2h0KHRoaXMsIHNpYmxpbmcpO1xuICAgICAgICAgICAgc2libGluZyA9IHBhcmVudC5SO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzaWJsaW5nLkMgPSBwYXJlbnQuQztcbiAgICAgICAgICBwYXJlbnQuQyA9IHNpYmxpbmcuUi5DID0gZmFsc2U7XG4gICAgICAgICAgUmVkQmxhY2tSb3RhdGVMZWZ0KHRoaXMsIHBhcmVudCk7XG4gICAgICAgICAgbm9kZSA9IHRoaXMuXztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc2libGluZyA9IHBhcmVudC5MO1xuICAgICAgICBpZiAoc2libGluZy5DKSB7XG4gICAgICAgICAgc2libGluZy5DID0gZmFsc2U7XG4gICAgICAgICAgcGFyZW50LkMgPSB0cnVlO1xuICAgICAgICAgIFJlZEJsYWNrUm90YXRlUmlnaHQodGhpcywgcGFyZW50KTtcbiAgICAgICAgICBzaWJsaW5nID0gcGFyZW50Lkw7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChzaWJsaW5nLkwgJiYgc2libGluZy5MLkMpXG4gICAgICAgICAgfHwgKHNpYmxpbmcuUiAmJiBzaWJsaW5nLlIuQykpIHtcbiAgICAgICAgICBpZiAoIXNpYmxpbmcuTCB8fCAhc2libGluZy5MLkMpIHtcbiAgICAgICAgICAgIHNpYmxpbmcuUi5DID0gZmFsc2U7XG4gICAgICAgICAgICBzaWJsaW5nLkMgPSB0cnVlO1xuICAgICAgICAgICAgUmVkQmxhY2tSb3RhdGVMZWZ0KHRoaXMsIHNpYmxpbmcpO1xuICAgICAgICAgICAgc2libGluZyA9IHBhcmVudC5MO1xuICAgICAgICAgIH1cbiAgICAgICAgICBzaWJsaW5nLkMgPSBwYXJlbnQuQztcbiAgICAgICAgICBwYXJlbnQuQyA9IHNpYmxpbmcuTC5DID0gZmFsc2U7XG4gICAgICAgICAgUmVkQmxhY2tSb3RhdGVSaWdodCh0aGlzLCBwYXJlbnQpO1xuICAgICAgICAgIG5vZGUgPSB0aGlzLl87XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNpYmxpbmcuQyA9IHRydWU7XG4gICAgICBub2RlID0gcGFyZW50O1xuICAgICAgcGFyZW50ID0gcGFyZW50LlU7XG4gICAgfSB3aGlsZSAoIW5vZGUuQyk7XG5cbiAgICBpZiAobm9kZSkgbm9kZS5DID0gZmFsc2U7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIFJlZEJsYWNrUm90YXRlTGVmdCh0cmVlLCBub2RlKSB7XG4gIHZhciBwID0gbm9kZSxcbiAgICAgIHEgPSBub2RlLlIsXG4gICAgICBwYXJlbnQgPSBwLlU7XG5cbiAgaWYgKHBhcmVudCkge1xuICAgIGlmIChwYXJlbnQuTCA9PT0gcCkgcGFyZW50LkwgPSBxO1xuICAgIGVsc2UgcGFyZW50LlIgPSBxO1xuICB9IGVsc2Uge1xuICAgIHRyZWUuXyA9IHE7XG4gIH1cblxuICBxLlUgPSBwYXJlbnQ7XG4gIHAuVSA9IHE7XG4gIHAuUiA9IHEuTDtcbiAgaWYgKHAuUikgcC5SLlUgPSBwO1xuICBxLkwgPSBwO1xufVxuXG5mdW5jdGlvbiBSZWRCbGFja1JvdGF0ZVJpZ2h0KHRyZWUsIG5vZGUpIHtcbiAgdmFyIHAgPSBub2RlLFxuICAgICAgcSA9IG5vZGUuTCxcbiAgICAgIHBhcmVudCA9IHAuVTtcblxuICBpZiAocGFyZW50KSB7XG4gICAgaWYgKHBhcmVudC5MID09PSBwKSBwYXJlbnQuTCA9IHE7XG4gICAgZWxzZSBwYXJlbnQuUiA9IHE7XG4gIH0gZWxzZSB7XG4gICAgdHJlZS5fID0gcTtcbiAgfVxuXG4gIHEuVSA9IHBhcmVudDtcbiAgcC5VID0gcTtcbiAgcC5MID0gcS5SO1xuICBpZiAocC5MKSBwLkwuVSA9IHA7XG4gIHEuUiA9IHA7XG59XG5cbmZ1bmN0aW9uIFJlZEJsYWNrRmlyc3Qobm9kZSkge1xuICB3aGlsZSAobm9kZS5MKSBub2RlID0gbm9kZS5MO1xuICByZXR1cm4gbm9kZTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlRWRnZShsZWZ0LCByaWdodCwgdjAsIHYxKSB7XG4gIHZhciBlZGdlID0gW251bGwsIG51bGxdLFxuICAgICAgaW5kZXggPSBlZGdlcy5wdXNoKGVkZ2UpIC0gMTtcbiAgZWRnZS5sZWZ0ID0gbGVmdDtcbiAgZWRnZS5yaWdodCA9IHJpZ2h0O1xuICBpZiAodjApIHNldEVkZ2VFbmQoZWRnZSwgbGVmdCwgcmlnaHQsIHYwKTtcbiAgaWYgKHYxKSBzZXRFZGdlRW5kKGVkZ2UsIHJpZ2h0LCBsZWZ0LCB2MSk7XG4gIGNlbGxzW2xlZnQuaW5kZXhdLmhhbGZlZGdlcy5wdXNoKGluZGV4KTtcbiAgY2VsbHNbcmlnaHQuaW5kZXhdLmhhbGZlZGdlcy5wdXNoKGluZGV4KTtcbiAgcmV0dXJuIGVkZ2U7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJvcmRlckVkZ2UobGVmdCwgdjAsIHYxKSB7XG4gIHZhciBlZGdlID0gW3YwLCB2MV07XG4gIGVkZ2UubGVmdCA9IGxlZnQ7XG4gIHJldHVybiBlZGdlO1xufVxuXG5mdW5jdGlvbiBzZXRFZGdlRW5kKGVkZ2UsIGxlZnQsIHJpZ2h0LCB2ZXJ0ZXgpIHtcbiAgaWYgKCFlZGdlWzBdICYmICFlZGdlWzFdKSB7XG4gICAgZWRnZVswXSA9IHZlcnRleDtcbiAgICBlZGdlLmxlZnQgPSBsZWZ0O1xuICAgIGVkZ2UucmlnaHQgPSByaWdodDtcbiAgfSBlbHNlIGlmIChlZGdlLmxlZnQgPT09IHJpZ2h0KSB7XG4gICAgZWRnZVsxXSA9IHZlcnRleDtcbiAgfSBlbHNlIHtcbiAgICBlZGdlWzBdID0gdmVydGV4O1xuICB9XG59XG5cbi8vIExpYW5n4oCTQmFyc2t5IGxpbmUgY2xpcHBpbmcuXG5mdW5jdGlvbiBjbGlwRWRnZShlZGdlLCB4MCwgeTAsIHgxLCB5MSkge1xuICB2YXIgYSA9IGVkZ2VbMF0sXG4gICAgICBiID0gZWRnZVsxXSxcbiAgICAgIGF4ID0gYVswXSxcbiAgICAgIGF5ID0gYVsxXSxcbiAgICAgIGJ4ID0gYlswXSxcbiAgICAgIGJ5ID0gYlsxXSxcbiAgICAgIHQwID0gMCxcbiAgICAgIHQxID0gMSxcbiAgICAgIGR4ID0gYnggLSBheCxcbiAgICAgIGR5ID0gYnkgLSBheSxcbiAgICAgIHI7XG5cbiAgciA9IHgwIC0gYXg7XG4gIGlmICghZHggJiYgciA+IDApIHJldHVybjtcbiAgciAvPSBkeDtcbiAgaWYgKGR4IDwgMCkge1xuICAgIGlmIChyIDwgdDApIHJldHVybjtcbiAgICBpZiAociA8IHQxKSB0MSA9IHI7XG4gIH0gZWxzZSBpZiAoZHggPiAwKSB7XG4gICAgaWYgKHIgPiB0MSkgcmV0dXJuO1xuICAgIGlmIChyID4gdDApIHQwID0gcjtcbiAgfVxuXG4gIHIgPSB4MSAtIGF4O1xuICBpZiAoIWR4ICYmIHIgPCAwKSByZXR1cm47XG4gIHIgLz0gZHg7XG4gIGlmIChkeCA8IDApIHtcbiAgICBpZiAociA+IHQxKSByZXR1cm47XG4gICAgaWYgKHIgPiB0MCkgdDAgPSByO1xuICB9IGVsc2UgaWYgKGR4ID4gMCkge1xuICAgIGlmIChyIDwgdDApIHJldHVybjtcbiAgICBpZiAociA8IHQxKSB0MSA9IHI7XG4gIH1cblxuICByID0geTAgLSBheTtcbiAgaWYgKCFkeSAmJiByID4gMCkgcmV0dXJuO1xuICByIC89IGR5O1xuICBpZiAoZHkgPCAwKSB7XG4gICAgaWYgKHIgPCB0MCkgcmV0dXJuO1xuICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgfSBlbHNlIGlmIChkeSA+IDApIHtcbiAgICBpZiAociA+IHQxKSByZXR1cm47XG4gICAgaWYgKHIgPiB0MCkgdDAgPSByO1xuICB9XG5cbiAgciA9IHkxIC0gYXk7XG4gIGlmICghZHkgJiYgciA8IDApIHJldHVybjtcbiAgciAvPSBkeTtcbiAgaWYgKGR5IDwgMCkge1xuICAgIGlmIChyID4gdDEpIHJldHVybjtcbiAgICBpZiAociA+IHQwKSB0MCA9IHI7XG4gIH0gZWxzZSBpZiAoZHkgPiAwKSB7XG4gICAgaWYgKHIgPCB0MCkgcmV0dXJuO1xuICAgIGlmIChyIDwgdDEpIHQxID0gcjtcbiAgfVxuXG4gIGlmICghKHQwID4gMCkgJiYgISh0MSA8IDEpKSByZXR1cm4gdHJ1ZTsgLy8gVE9ETyBCZXR0ZXIgY2hlY2s/XG5cbiAgaWYgKHQwID4gMCkgZWRnZVswXSA9IFtheCArIHQwICogZHgsIGF5ICsgdDAgKiBkeV07XG4gIGlmICh0MSA8IDEpIGVkZ2VbMV0gPSBbYXggKyB0MSAqIGR4LCBheSArIHQxICogZHldO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gY29ubmVjdEVkZ2UoZWRnZSwgeDAsIHkwLCB4MSwgeTEpIHtcbiAgdmFyIHYxID0gZWRnZVsxXTtcbiAgaWYgKHYxKSByZXR1cm4gdHJ1ZTtcblxuICB2YXIgdjAgPSBlZGdlWzBdLFxuICAgICAgbGVmdCA9IGVkZ2UubGVmdCxcbiAgICAgIHJpZ2h0ID0gZWRnZS5yaWdodCxcbiAgICAgIGx4ID0gbGVmdFswXSxcbiAgICAgIGx5ID0gbGVmdFsxXSxcbiAgICAgIHJ4ID0gcmlnaHRbMF0sXG4gICAgICByeSA9IHJpZ2h0WzFdLFxuICAgICAgZnggPSAobHggKyByeCkgLyAyLFxuICAgICAgZnkgPSAobHkgKyByeSkgLyAyLFxuICAgICAgZm0sXG4gICAgICBmYjtcblxuICBpZiAocnkgPT09IGx5KSB7XG4gICAgaWYgKGZ4IDwgeDAgfHwgZnggPj0geDEpIHJldHVybjtcbiAgICBpZiAobHggPiByeCkge1xuICAgICAgaWYgKCF2MCkgdjAgPSBbZngsIHkwXTtcbiAgICAgIGVsc2UgaWYgKHYwWzFdID49IHkxKSByZXR1cm47XG4gICAgICB2MSA9IFtmeCwgeTFdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIXYwKSB2MCA9IFtmeCwgeTFdO1xuICAgICAgZWxzZSBpZiAodjBbMV0gPCB5MCkgcmV0dXJuO1xuICAgICAgdjEgPSBbZngsIHkwXTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgZm0gPSAobHggLSByeCkgLyAocnkgLSBseSk7XG4gICAgZmIgPSBmeSAtIGZtICogZng7XG4gICAgaWYgKGZtIDwgLTEgfHwgZm0gPiAxKSB7XG4gICAgICBpZiAobHggPiByeCkge1xuICAgICAgICBpZiAoIXYwKSB2MCA9IFsoeTAgLSBmYikgLyBmbSwgeTBdO1xuICAgICAgICBlbHNlIGlmICh2MFsxXSA+PSB5MSkgcmV0dXJuO1xuICAgICAgICB2MSA9IFsoeTEgLSBmYikgLyBmbSwgeTFdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCF2MCkgdjAgPSBbKHkxIC0gZmIpIC8gZm0sIHkxXTtcbiAgICAgICAgZWxzZSBpZiAodjBbMV0gPCB5MCkgcmV0dXJuO1xuICAgICAgICB2MSA9IFsoeTAgLSBmYikgLyBmbSwgeTBdO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAobHkgPCByeSkge1xuICAgICAgICBpZiAoIXYwKSB2MCA9IFt4MCwgZm0gKiB4MCArIGZiXTtcbiAgICAgICAgZWxzZSBpZiAodjBbMF0gPj0geDEpIHJldHVybjtcbiAgICAgICAgdjEgPSBbeDEsIGZtICogeDEgKyBmYl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIXYwKSB2MCA9IFt4MSwgZm0gKiB4MSArIGZiXTtcbiAgICAgICAgZWxzZSBpZiAodjBbMF0gPCB4MCkgcmV0dXJuO1xuICAgICAgICB2MSA9IFt4MCwgZm0gKiB4MCArIGZiXTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlZGdlWzBdID0gdjA7XG4gIGVkZ2VbMV0gPSB2MTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGNsaXBFZGdlcyh4MCwgeTAsIHgxLCB5MSkge1xuICB2YXIgaSA9IGVkZ2VzLmxlbmd0aCxcbiAgICAgIGVkZ2U7XG5cbiAgd2hpbGUgKGktLSkge1xuICAgIGlmICghY29ubmVjdEVkZ2UoZWRnZSA9IGVkZ2VzW2ldLCB4MCwgeTAsIHgxLCB5MSlcbiAgICAgICAgfHwgIWNsaXBFZGdlKGVkZ2UsIHgwLCB5MCwgeDEsIHkxKVxuICAgICAgICB8fCAhKE1hdGguYWJzKGVkZ2VbMF1bMF0gLSBlZGdlWzFdWzBdKSA+IGVwc2lsb25cbiAgICAgICAgICAgIHx8IE1hdGguYWJzKGVkZ2VbMF1bMV0gLSBlZGdlWzFdWzFdKSA+IGVwc2lsb24pKSB7XG4gICAgICBkZWxldGUgZWRnZXNbaV07XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUNlbGwoc2l0ZSkge1xuICByZXR1cm4gY2VsbHNbc2l0ZS5pbmRleF0gPSB7XG4gICAgc2l0ZTogc2l0ZSxcbiAgICBoYWxmZWRnZXM6IFtdXG4gIH07XG59XG5cbmZ1bmN0aW9uIGNlbGxIYWxmZWRnZUFuZ2xlKGNlbGwsIGVkZ2UpIHtcbiAgdmFyIHNpdGUgPSBjZWxsLnNpdGUsXG4gICAgICB2YSA9IGVkZ2UubGVmdCxcbiAgICAgIHZiID0gZWRnZS5yaWdodDtcbiAgaWYgKHNpdGUgPT09IHZiKSB2YiA9IHZhLCB2YSA9IHNpdGU7XG4gIGlmICh2YikgcmV0dXJuIE1hdGguYXRhbjIodmJbMV0gLSB2YVsxXSwgdmJbMF0gLSB2YVswXSk7XG4gIGlmIChzaXRlID09PSB2YSkgdmEgPSBlZGdlWzFdLCB2YiA9IGVkZ2VbMF07XG4gIGVsc2UgdmEgPSBlZGdlWzBdLCB2YiA9IGVkZ2VbMV07XG4gIHJldHVybiBNYXRoLmF0YW4yKHZhWzBdIC0gdmJbMF0sIHZiWzFdIC0gdmFbMV0pO1xufVxuXG5mdW5jdGlvbiBjZWxsSGFsZmVkZ2VTdGFydChjZWxsLCBlZGdlKSB7XG4gIHJldHVybiBlZGdlWysoZWRnZS5sZWZ0ICE9PSBjZWxsLnNpdGUpXTtcbn1cblxuZnVuY3Rpb24gY2VsbEhhbGZlZGdlRW5kKGNlbGwsIGVkZ2UpIHtcbiAgcmV0dXJuIGVkZ2VbKyhlZGdlLmxlZnQgPT09IGNlbGwuc2l0ZSldO1xufVxuXG5mdW5jdGlvbiBzb3J0Q2VsbEhhbGZlZGdlcygpIHtcbiAgZm9yICh2YXIgaSA9IDAsIG4gPSBjZWxscy5sZW5ndGgsIGNlbGwsIGhhbGZlZGdlcywgaiwgbTsgaSA8IG47ICsraSkge1xuICAgIGlmICgoY2VsbCA9IGNlbGxzW2ldKSAmJiAobSA9IChoYWxmZWRnZXMgPSBjZWxsLmhhbGZlZGdlcykubGVuZ3RoKSkge1xuICAgICAgdmFyIGluZGV4ID0gbmV3IEFycmF5KG0pLFxuICAgICAgICAgIGFycmF5ID0gbmV3IEFycmF5KG0pO1xuICAgICAgZm9yIChqID0gMDsgaiA8IG07ICsraikgaW5kZXhbal0gPSBqLCBhcnJheVtqXSA9IGNlbGxIYWxmZWRnZUFuZ2xlKGNlbGwsIGVkZ2VzW2hhbGZlZGdlc1tqXV0pO1xuICAgICAgaW5kZXguc29ydChmdW5jdGlvbihpLCBqKSB7IHJldHVybiBhcnJheVtqXSAtIGFycmF5W2ldOyB9KTtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIGFycmF5W2pdID0gaGFsZmVkZ2VzW2luZGV4W2pdXTtcbiAgICAgIGZvciAoaiA9IDA7IGogPCBtOyArK2opIGhhbGZlZGdlc1tqXSA9IGFycmF5W2pdO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBjbGlwQ2VsbHMoeDAsIHkwLCB4MSwgeTEpIHtcbiAgdmFyIG5DZWxscyA9IGNlbGxzLmxlbmd0aCxcbiAgICAgIGlDZWxsLFxuICAgICAgY2VsbCxcbiAgICAgIHNpdGUsXG4gICAgICBpSGFsZmVkZ2UsXG4gICAgICBoYWxmZWRnZXMsXG4gICAgICBuSGFsZmVkZ2VzLFxuICAgICAgc3RhcnQsXG4gICAgICBzdGFydFgsXG4gICAgICBzdGFydFksXG4gICAgICBlbmQsXG4gICAgICBlbmRYLFxuICAgICAgZW5kWSxcbiAgICAgIGNvdmVyID0gdHJ1ZTtcblxuICBmb3IgKGlDZWxsID0gMDsgaUNlbGwgPCBuQ2VsbHM7ICsraUNlbGwpIHtcbiAgICBpZiAoY2VsbCA9IGNlbGxzW2lDZWxsXSkge1xuICAgICAgc2l0ZSA9IGNlbGwuc2l0ZTtcbiAgICAgIGhhbGZlZGdlcyA9IGNlbGwuaGFsZmVkZ2VzO1xuICAgICAgaUhhbGZlZGdlID0gaGFsZmVkZ2VzLmxlbmd0aDtcblxuICAgICAgLy8gUmVtb3ZlIGFueSBkYW5nbGluZyBjbGlwcGVkIGVkZ2VzLlxuICAgICAgd2hpbGUgKGlIYWxmZWRnZS0tKSB7XG4gICAgICAgIGlmICghZWRnZXNbaGFsZmVkZ2VzW2lIYWxmZWRnZV1dKSB7XG4gICAgICAgICAgaGFsZmVkZ2VzLnNwbGljZShpSGFsZmVkZ2UsIDEpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEluc2VydCBhbnkgYm9yZGVyIGVkZ2VzIGFzIG5lY2Vzc2FyeS5cbiAgICAgIGlIYWxmZWRnZSA9IDAsIG5IYWxmZWRnZXMgPSBoYWxmZWRnZXMubGVuZ3RoO1xuICAgICAgd2hpbGUgKGlIYWxmZWRnZSA8IG5IYWxmZWRnZXMpIHtcbiAgICAgICAgZW5kID0gY2VsbEhhbGZlZGdlRW5kKGNlbGwsIGVkZ2VzW2hhbGZlZGdlc1tpSGFsZmVkZ2VdXSksIGVuZFggPSBlbmRbMF0sIGVuZFkgPSBlbmRbMV07XG4gICAgICAgIHN0YXJ0ID0gY2VsbEhhbGZlZGdlU3RhcnQoY2VsbCwgZWRnZXNbaGFsZmVkZ2VzWysraUhhbGZlZGdlICUgbkhhbGZlZGdlc11dKSwgc3RhcnRYID0gc3RhcnRbMF0sIHN0YXJ0WSA9IHN0YXJ0WzFdO1xuICAgICAgICBpZiAoTWF0aC5hYnMoZW5kWCAtIHN0YXJ0WCkgPiBlcHNpbG9uIHx8IE1hdGguYWJzKGVuZFkgLSBzdGFydFkpID4gZXBzaWxvbikge1xuICAgICAgICAgIGhhbGZlZGdlcy5zcGxpY2UoaUhhbGZlZGdlLCAwLCBlZGdlcy5wdXNoKGNyZWF0ZUJvcmRlckVkZ2Uoc2l0ZSwgZW5kLFxuICAgICAgICAgICAgICBNYXRoLmFicyhlbmRYIC0geDApIDwgZXBzaWxvbiAmJiB5MSAtIGVuZFkgPiBlcHNpbG9uID8gW3gwLCBNYXRoLmFicyhzdGFydFggLSB4MCkgPCBlcHNpbG9uID8gc3RhcnRZIDogeTFdXG4gICAgICAgICAgICAgIDogTWF0aC5hYnMoZW5kWSAtIHkxKSA8IGVwc2lsb24gJiYgeDEgLSBlbmRYID4gZXBzaWxvbiA/IFtNYXRoLmFicyhzdGFydFkgLSB5MSkgPCBlcHNpbG9uID8gc3RhcnRYIDogeDEsIHkxXVxuICAgICAgICAgICAgICA6IE1hdGguYWJzKGVuZFggLSB4MSkgPCBlcHNpbG9uICYmIGVuZFkgLSB5MCA+IGVwc2lsb24gPyBbeDEsIE1hdGguYWJzKHN0YXJ0WCAtIHgxKSA8IGVwc2lsb24gPyBzdGFydFkgOiB5MF1cbiAgICAgICAgICAgICAgOiBNYXRoLmFicyhlbmRZIC0geTApIDwgZXBzaWxvbiAmJiBlbmRYIC0geDAgPiBlcHNpbG9uID8gW01hdGguYWJzKHN0YXJ0WSAtIHkwKSA8IGVwc2lsb24gPyBzdGFydFggOiB4MCwgeTBdXG4gICAgICAgICAgICAgIDogbnVsbCkpIC0gMSk7XG4gICAgICAgICAgKytuSGFsZmVkZ2VzO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChuSGFsZmVkZ2VzKSBjb3ZlciA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8vIElmIHRoZXJlIHdlcmVu4oCZdCBhbnkgZWRnZXMsIGhhdmUgdGhlIGNsb3Nlc3Qgc2l0ZSBjb3ZlciB0aGUgZXh0ZW50LlxuICAvLyBJdCBkb2VzbuKAmXQgbWF0dGVyIHdoaWNoIGNvcm5lciBvZiB0aGUgZXh0ZW50IHdlIG1lYXN1cmUhXG4gIGlmIChjb3Zlcikge1xuICAgIHZhciBkeCwgZHksIGQyLCBkYyA9IEluZmluaXR5O1xuXG4gICAgZm9yIChpQ2VsbCA9IDAsIGNvdmVyID0gbnVsbDsgaUNlbGwgPCBuQ2VsbHM7ICsraUNlbGwpIHtcbiAgICAgIGlmIChjZWxsID0gY2VsbHNbaUNlbGxdKSB7XG4gICAgICAgIHNpdGUgPSBjZWxsLnNpdGU7XG4gICAgICAgIGR4ID0gc2l0ZVswXSAtIHgwO1xuICAgICAgICBkeSA9IHNpdGVbMV0gLSB5MDtcbiAgICAgICAgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeTtcbiAgICAgICAgaWYgKGQyIDwgZGMpIGRjID0gZDIsIGNvdmVyID0gY2VsbDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY292ZXIpIHtcbiAgICAgIHZhciB2MDAgPSBbeDAsIHkwXSwgdjAxID0gW3gwLCB5MV0sIHYxMSA9IFt4MSwgeTFdLCB2MTAgPSBbeDEsIHkwXTtcbiAgICAgIGNvdmVyLmhhbGZlZGdlcy5wdXNoKFxuICAgICAgICBlZGdlcy5wdXNoKGNyZWF0ZUJvcmRlckVkZ2Uoc2l0ZSA9IGNvdmVyLnNpdGUsIHYwMCwgdjAxKSkgLSAxLFxuICAgICAgICBlZGdlcy5wdXNoKGNyZWF0ZUJvcmRlckVkZ2Uoc2l0ZSwgdjAxLCB2MTEpKSAtIDEsXG4gICAgICAgIGVkZ2VzLnB1c2goY3JlYXRlQm9yZGVyRWRnZShzaXRlLCB2MTEsIHYxMCkpIC0gMSxcbiAgICAgICAgZWRnZXMucHVzaChjcmVhdGVCb3JkZXJFZGdlKHNpdGUsIHYxMCwgdjAwKSkgLSAxXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIC8vIExhc3RseSBkZWxldGUgYW55IGNlbGxzIHdpdGggbm8gZWRnZXM7IHRoZXNlIHdlcmUgZW50aXJlbHkgY2xpcHBlZC5cbiAgZm9yIChpQ2VsbCA9IDA7IGlDZWxsIDwgbkNlbGxzOyArK2lDZWxsKSB7XG4gICAgaWYgKGNlbGwgPSBjZWxsc1tpQ2VsbF0pIHtcbiAgICAgIGlmICghY2VsbC5oYWxmZWRnZXMubGVuZ3RoKSB7XG4gICAgICAgIGRlbGV0ZSBjZWxsc1tpQ2VsbF07XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbnZhciBjaXJjbGVQb29sID0gW107XG5cbnZhciBmaXJzdENpcmNsZTtcblxuZnVuY3Rpb24gQ2lyY2xlKCkge1xuICBSZWRCbGFja05vZGUodGhpcyk7XG4gIHRoaXMueCA9XG4gIHRoaXMueSA9XG4gIHRoaXMuYXJjID1cbiAgdGhpcy5zaXRlID1cbiAgdGhpcy5jeSA9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGF0dGFjaENpcmNsZShhcmMpIHtcbiAgdmFyIGxBcmMgPSBhcmMuUCxcbiAgICAgIHJBcmMgPSBhcmMuTjtcblxuICBpZiAoIWxBcmMgfHwgIXJBcmMpIHJldHVybjtcblxuICB2YXIgbFNpdGUgPSBsQXJjLnNpdGUsXG4gICAgICBjU2l0ZSA9IGFyYy5zaXRlLFxuICAgICAgclNpdGUgPSByQXJjLnNpdGU7XG5cbiAgaWYgKGxTaXRlID09PSByU2l0ZSkgcmV0dXJuO1xuXG4gIHZhciBieCA9IGNTaXRlWzBdLFxuICAgICAgYnkgPSBjU2l0ZVsxXSxcbiAgICAgIGF4ID0gbFNpdGVbMF0gLSBieCxcbiAgICAgIGF5ID0gbFNpdGVbMV0gLSBieSxcbiAgICAgIGN4ID0gclNpdGVbMF0gLSBieCxcbiAgICAgIGN5ID0gclNpdGVbMV0gLSBieTtcblxuICB2YXIgZCA9IDIgKiAoYXggKiBjeSAtIGF5ICogY3gpO1xuICBpZiAoZCA+PSAtZXBzaWxvbjIpIHJldHVybjtcblxuICB2YXIgaGEgPSBheCAqIGF4ICsgYXkgKiBheSxcbiAgICAgIGhjID0gY3ggKiBjeCArIGN5ICogY3ksXG4gICAgICB4ID0gKGN5ICogaGEgLSBheSAqIGhjKSAvIGQsXG4gICAgICB5ID0gKGF4ICogaGMgLSBjeCAqIGhhKSAvIGQ7XG5cbiAgdmFyIGNpcmNsZSA9IGNpcmNsZVBvb2wucG9wKCkgfHwgbmV3IENpcmNsZTtcbiAgY2lyY2xlLmFyYyA9IGFyYztcbiAgY2lyY2xlLnNpdGUgPSBjU2l0ZTtcbiAgY2lyY2xlLnggPSB4ICsgYng7XG4gIGNpcmNsZS55ID0gKGNpcmNsZS5jeSA9IHkgKyBieSkgKyBNYXRoLnNxcnQoeCAqIHggKyB5ICogeSk7IC8vIHkgYm90dG9tXG5cbiAgYXJjLmNpcmNsZSA9IGNpcmNsZTtcblxuICB2YXIgYmVmb3JlID0gbnVsbCxcbiAgICAgIG5vZGUgPSBjaXJjbGVzLl87XG5cbiAgd2hpbGUgKG5vZGUpIHtcbiAgICBpZiAoY2lyY2xlLnkgPCBub2RlLnkgfHwgKGNpcmNsZS55ID09PSBub2RlLnkgJiYgY2lyY2xlLnggPD0gbm9kZS54KSkge1xuICAgICAgaWYgKG5vZGUuTCkgbm9kZSA9IG5vZGUuTDtcbiAgICAgIGVsc2UgeyBiZWZvcmUgPSBub2RlLlA7IGJyZWFrOyB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChub2RlLlIpIG5vZGUgPSBub2RlLlI7XG4gICAgICBlbHNlIHsgYmVmb3JlID0gbm9kZTsgYnJlYWs7IH1cbiAgICB9XG4gIH1cblxuICBjaXJjbGVzLmluc2VydChiZWZvcmUsIGNpcmNsZSk7XG4gIGlmICghYmVmb3JlKSBmaXJzdENpcmNsZSA9IGNpcmNsZTtcbn1cblxuZnVuY3Rpb24gZGV0YWNoQ2lyY2xlKGFyYykge1xuICB2YXIgY2lyY2xlID0gYXJjLmNpcmNsZTtcbiAgaWYgKGNpcmNsZSkge1xuICAgIGlmICghY2lyY2xlLlApIGZpcnN0Q2lyY2xlID0gY2lyY2xlLk47XG4gICAgY2lyY2xlcy5yZW1vdmUoY2lyY2xlKTtcbiAgICBjaXJjbGVQb29sLnB1c2goY2lyY2xlKTtcbiAgICBSZWRCbGFja05vZGUoY2lyY2xlKTtcbiAgICBhcmMuY2lyY2xlID0gbnVsbDtcbiAgfVxufVxuXG52YXIgYmVhY2hQb29sID0gW107XG5cbmZ1bmN0aW9uIEJlYWNoKCkge1xuICBSZWRCbGFja05vZGUodGhpcyk7XG4gIHRoaXMuZWRnZSA9XG4gIHRoaXMuc2l0ZSA9XG4gIHRoaXMuY2lyY2xlID0gbnVsbDtcbn1cblxuZnVuY3Rpb24gY3JlYXRlQmVhY2goc2l0ZSkge1xuICB2YXIgYmVhY2ggPSBiZWFjaFBvb2wucG9wKCkgfHwgbmV3IEJlYWNoO1xuICBiZWFjaC5zaXRlID0gc2l0ZTtcbiAgcmV0dXJuIGJlYWNoO1xufVxuXG5mdW5jdGlvbiBkZXRhY2hCZWFjaChiZWFjaCkge1xuICBkZXRhY2hDaXJjbGUoYmVhY2gpO1xuICBiZWFjaGVzLnJlbW92ZShiZWFjaCk7XG4gIGJlYWNoUG9vbC5wdXNoKGJlYWNoKTtcbiAgUmVkQmxhY2tOb2RlKGJlYWNoKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlQmVhY2goYmVhY2gpIHtcbiAgdmFyIGNpcmNsZSA9IGJlYWNoLmNpcmNsZSxcbiAgICAgIHggPSBjaXJjbGUueCxcbiAgICAgIHkgPSBjaXJjbGUuY3ksXG4gICAgICB2ZXJ0ZXggPSBbeCwgeV0sXG4gICAgICBwcmV2aW91cyA9IGJlYWNoLlAsXG4gICAgICBuZXh0ID0gYmVhY2guTixcbiAgICAgIGRpc2FwcGVhcmluZyA9IFtiZWFjaF07XG5cbiAgZGV0YWNoQmVhY2goYmVhY2gpO1xuXG4gIHZhciBsQXJjID0gcHJldmlvdXM7XG4gIHdoaWxlIChsQXJjLmNpcmNsZVxuICAgICAgJiYgTWF0aC5hYnMoeCAtIGxBcmMuY2lyY2xlLngpIDwgZXBzaWxvblxuICAgICAgJiYgTWF0aC5hYnMoeSAtIGxBcmMuY2lyY2xlLmN5KSA8IGVwc2lsb24pIHtcbiAgICBwcmV2aW91cyA9IGxBcmMuUDtcbiAgICBkaXNhcHBlYXJpbmcudW5zaGlmdChsQXJjKTtcbiAgICBkZXRhY2hCZWFjaChsQXJjKTtcbiAgICBsQXJjID0gcHJldmlvdXM7XG4gIH1cblxuICBkaXNhcHBlYXJpbmcudW5zaGlmdChsQXJjKTtcbiAgZGV0YWNoQ2lyY2xlKGxBcmMpO1xuXG4gIHZhciByQXJjID0gbmV4dDtcbiAgd2hpbGUgKHJBcmMuY2lyY2xlXG4gICAgICAmJiBNYXRoLmFicyh4IC0gckFyYy5jaXJjbGUueCkgPCBlcHNpbG9uXG4gICAgICAmJiBNYXRoLmFicyh5IC0gckFyYy5jaXJjbGUuY3kpIDwgZXBzaWxvbikge1xuICAgIG5leHQgPSByQXJjLk47XG4gICAgZGlzYXBwZWFyaW5nLnB1c2gockFyYyk7XG4gICAgZGV0YWNoQmVhY2gockFyYyk7XG4gICAgckFyYyA9IG5leHQ7XG4gIH1cblxuICBkaXNhcHBlYXJpbmcucHVzaChyQXJjKTtcbiAgZGV0YWNoQ2lyY2xlKHJBcmMpO1xuXG4gIHZhciBuQXJjcyA9IGRpc2FwcGVhcmluZy5sZW5ndGgsXG4gICAgICBpQXJjO1xuICBmb3IgKGlBcmMgPSAxOyBpQXJjIDwgbkFyY3M7ICsraUFyYykge1xuICAgIHJBcmMgPSBkaXNhcHBlYXJpbmdbaUFyY107XG4gICAgbEFyYyA9IGRpc2FwcGVhcmluZ1tpQXJjIC0gMV07XG4gICAgc2V0RWRnZUVuZChyQXJjLmVkZ2UsIGxBcmMuc2l0ZSwgckFyYy5zaXRlLCB2ZXJ0ZXgpO1xuICB9XG5cbiAgbEFyYyA9IGRpc2FwcGVhcmluZ1swXTtcbiAgckFyYyA9IGRpc2FwcGVhcmluZ1tuQXJjcyAtIDFdO1xuICByQXJjLmVkZ2UgPSBjcmVhdGVFZGdlKGxBcmMuc2l0ZSwgckFyYy5zaXRlLCBudWxsLCB2ZXJ0ZXgpO1xuXG4gIGF0dGFjaENpcmNsZShsQXJjKTtcbiAgYXR0YWNoQ2lyY2xlKHJBcmMpO1xufVxuXG5mdW5jdGlvbiBhZGRCZWFjaChzaXRlKSB7XG4gIHZhciB4ID0gc2l0ZVswXSxcbiAgICAgIGRpcmVjdHJpeCA9IHNpdGVbMV0sXG4gICAgICBsQXJjLFxuICAgICAgckFyYyxcbiAgICAgIGR4bCxcbiAgICAgIGR4cixcbiAgICAgIG5vZGUgPSBiZWFjaGVzLl87XG5cbiAgd2hpbGUgKG5vZGUpIHtcbiAgICBkeGwgPSBsZWZ0QnJlYWtQb2ludChub2RlLCBkaXJlY3RyaXgpIC0geDtcbiAgICBpZiAoZHhsID4gZXBzaWxvbikgbm9kZSA9IG5vZGUuTDsgZWxzZSB7XG4gICAgICBkeHIgPSB4IC0gcmlnaHRCcmVha1BvaW50KG5vZGUsIGRpcmVjdHJpeCk7XG4gICAgICBpZiAoZHhyID4gZXBzaWxvbikge1xuICAgICAgICBpZiAoIW5vZGUuUikge1xuICAgICAgICAgIGxBcmMgPSBub2RlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIG5vZGUgPSBub2RlLlI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZHhsID4gLWVwc2lsb24pIHtcbiAgICAgICAgICBsQXJjID0gbm9kZS5QO1xuICAgICAgICAgIHJBcmMgPSBub2RlO1xuICAgICAgICB9IGVsc2UgaWYgKGR4ciA+IC1lcHNpbG9uKSB7XG4gICAgICAgICAgbEFyYyA9IG5vZGU7XG4gICAgICAgICAgckFyYyA9IG5vZGUuTjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsQXJjID0gckFyYyA9IG5vZGU7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY3JlYXRlQ2VsbChzaXRlKTtcbiAgdmFyIG5ld0FyYyA9IGNyZWF0ZUJlYWNoKHNpdGUpO1xuICBiZWFjaGVzLmluc2VydChsQXJjLCBuZXdBcmMpO1xuXG4gIGlmICghbEFyYyAmJiAhckFyYykgcmV0dXJuO1xuXG4gIGlmIChsQXJjID09PSByQXJjKSB7XG4gICAgZGV0YWNoQ2lyY2xlKGxBcmMpO1xuICAgIHJBcmMgPSBjcmVhdGVCZWFjaChsQXJjLnNpdGUpO1xuICAgIGJlYWNoZXMuaW5zZXJ0KG5ld0FyYywgckFyYyk7XG4gICAgbmV3QXJjLmVkZ2UgPSByQXJjLmVkZ2UgPSBjcmVhdGVFZGdlKGxBcmMuc2l0ZSwgbmV3QXJjLnNpdGUpO1xuICAgIGF0dGFjaENpcmNsZShsQXJjKTtcbiAgICBhdHRhY2hDaXJjbGUockFyYyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFyQXJjKSB7IC8vICYmIGxBcmNcbiAgICBuZXdBcmMuZWRnZSA9IGNyZWF0ZUVkZ2UobEFyYy5zaXRlLCBuZXdBcmMuc2l0ZSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gZWxzZSBsQXJjICE9PSByQXJjXG4gIGRldGFjaENpcmNsZShsQXJjKTtcbiAgZGV0YWNoQ2lyY2xlKHJBcmMpO1xuXG4gIHZhciBsU2l0ZSA9IGxBcmMuc2l0ZSxcbiAgICAgIGF4ID0gbFNpdGVbMF0sXG4gICAgICBheSA9IGxTaXRlWzFdLFxuICAgICAgYnggPSBzaXRlWzBdIC0gYXgsXG4gICAgICBieSA9IHNpdGVbMV0gLSBheSxcbiAgICAgIHJTaXRlID0gckFyYy5zaXRlLFxuICAgICAgY3ggPSByU2l0ZVswXSAtIGF4LFxuICAgICAgY3kgPSByU2l0ZVsxXSAtIGF5LFxuICAgICAgZCA9IDIgKiAoYnggKiBjeSAtIGJ5ICogY3gpLFxuICAgICAgaGIgPSBieCAqIGJ4ICsgYnkgKiBieSxcbiAgICAgIGhjID0gY3ggKiBjeCArIGN5ICogY3ksXG4gICAgICB2ZXJ0ZXggPSBbKGN5ICogaGIgLSBieSAqIGhjKSAvIGQgKyBheCwgKGJ4ICogaGMgLSBjeCAqIGhiKSAvIGQgKyBheV07XG5cbiAgc2V0RWRnZUVuZChyQXJjLmVkZ2UsIGxTaXRlLCByU2l0ZSwgdmVydGV4KTtcbiAgbmV3QXJjLmVkZ2UgPSBjcmVhdGVFZGdlKGxTaXRlLCBzaXRlLCBudWxsLCB2ZXJ0ZXgpO1xuICByQXJjLmVkZ2UgPSBjcmVhdGVFZGdlKHNpdGUsIHJTaXRlLCBudWxsLCB2ZXJ0ZXgpO1xuICBhdHRhY2hDaXJjbGUobEFyYyk7XG4gIGF0dGFjaENpcmNsZShyQXJjKTtcbn1cblxuZnVuY3Rpb24gbGVmdEJyZWFrUG9pbnQoYXJjLCBkaXJlY3RyaXgpIHtcbiAgdmFyIHNpdGUgPSBhcmMuc2l0ZSxcbiAgICAgIHJmb2N4ID0gc2l0ZVswXSxcbiAgICAgIHJmb2N5ID0gc2l0ZVsxXSxcbiAgICAgIHBieTIgPSByZm9jeSAtIGRpcmVjdHJpeDtcblxuICBpZiAoIXBieTIpIHJldHVybiByZm9jeDtcblxuICB2YXIgbEFyYyA9IGFyYy5QO1xuICBpZiAoIWxBcmMpIHJldHVybiAtSW5maW5pdHk7XG5cbiAgc2l0ZSA9IGxBcmMuc2l0ZTtcbiAgdmFyIGxmb2N4ID0gc2l0ZVswXSxcbiAgICAgIGxmb2N5ID0gc2l0ZVsxXSxcbiAgICAgIHBsYnkyID0gbGZvY3kgLSBkaXJlY3RyaXg7XG5cbiAgaWYgKCFwbGJ5MikgcmV0dXJuIGxmb2N4O1xuXG4gIHZhciBobCA9IGxmb2N4IC0gcmZvY3gsXG4gICAgICBhYnkyID0gMSAvIHBieTIgLSAxIC8gcGxieTIsXG4gICAgICBiID0gaGwgLyBwbGJ5MjtcblxuICBpZiAoYWJ5MikgcmV0dXJuICgtYiArIE1hdGguc3FydChiICogYiAtIDIgKiBhYnkyICogKGhsICogaGwgLyAoLTIgKiBwbGJ5MikgLSBsZm9jeSArIHBsYnkyIC8gMiArIHJmb2N5IC0gcGJ5MiAvIDIpKSkgLyBhYnkyICsgcmZvY3g7XG5cbiAgcmV0dXJuIChyZm9jeCArIGxmb2N4KSAvIDI7XG59XG5cbmZ1bmN0aW9uIHJpZ2h0QnJlYWtQb2ludChhcmMsIGRpcmVjdHJpeCkge1xuICB2YXIgckFyYyA9IGFyYy5OO1xuICBpZiAockFyYykgcmV0dXJuIGxlZnRCcmVha1BvaW50KHJBcmMsIGRpcmVjdHJpeCk7XG4gIHZhciBzaXRlID0gYXJjLnNpdGU7XG4gIHJldHVybiBzaXRlWzFdID09PSBkaXJlY3RyaXggPyBzaXRlWzBdIDogSW5maW5pdHk7XG59XG5cbnZhciBlcHNpbG9uID0gMWUtNjtcbnZhciBlcHNpbG9uMiA9IDFlLTEyO1xudmFyIGJlYWNoZXM7XG52YXIgY2VsbHM7XG52YXIgY2lyY2xlcztcbnZhciBlZGdlcztcblxuZnVuY3Rpb24gdHJpYW5nbGVBcmVhKGEsIGIsIGMpIHtcbiAgcmV0dXJuIChhWzBdIC0gY1swXSkgKiAoYlsxXSAtIGFbMV0pIC0gKGFbMF0gLSBiWzBdKSAqIChjWzFdIC0gYVsxXSk7XG59XG5cbmZ1bmN0aW9uIGxleGljb2dyYXBoaWMoYSwgYikge1xuICByZXR1cm4gYlsxXSAtIGFbMV1cbiAgICAgIHx8IGJbMF0gLSBhWzBdO1xufVxuXG5mdW5jdGlvbiBEaWFncmFtKHNpdGVzLCBleHRlbnQpIHtcbiAgdmFyIHNpdGUgPSBzaXRlcy5zb3J0KGxleGljb2dyYXBoaWMpLnBvcCgpLFxuICAgICAgeCxcbiAgICAgIHksXG4gICAgICBjaXJjbGU7XG5cbiAgZWRnZXMgPSBbXTtcbiAgY2VsbHMgPSBuZXcgQXJyYXkoc2l0ZXMubGVuZ3RoKTtcbiAgYmVhY2hlcyA9IG5ldyBSZWRCbGFja1RyZWU7XG4gIGNpcmNsZXMgPSBuZXcgUmVkQmxhY2tUcmVlO1xuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgY2lyY2xlID0gZmlyc3RDaXJjbGU7XG4gICAgaWYgKHNpdGUgJiYgKCFjaXJjbGUgfHwgc2l0ZVsxXSA8IGNpcmNsZS55IHx8IChzaXRlWzFdID09PSBjaXJjbGUueSAmJiBzaXRlWzBdIDwgY2lyY2xlLngpKSkge1xuICAgICAgaWYgKHNpdGVbMF0gIT09IHggfHwgc2l0ZVsxXSAhPT0geSkge1xuICAgICAgICBhZGRCZWFjaChzaXRlKTtcbiAgICAgICAgeCA9IHNpdGVbMF0sIHkgPSBzaXRlWzFdO1xuICAgICAgfVxuICAgICAgc2l0ZSA9IHNpdGVzLnBvcCgpO1xuICAgIH0gZWxzZSBpZiAoY2lyY2xlKSB7XG4gICAgICByZW1vdmVCZWFjaChjaXJjbGUuYXJjKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgc29ydENlbGxIYWxmZWRnZXMoKTtcblxuICBpZiAoZXh0ZW50KSB7XG4gICAgdmFyIHgwID0gK2V4dGVudFswXVswXSxcbiAgICAgICAgeTAgPSArZXh0ZW50WzBdWzFdLFxuICAgICAgICB4MSA9ICtleHRlbnRbMV1bMF0sXG4gICAgICAgIHkxID0gK2V4dGVudFsxXVsxXTtcbiAgICBjbGlwRWRnZXMoeDAsIHkwLCB4MSwgeTEpO1xuICAgIGNsaXBDZWxscyh4MCwgeTAsIHgxLCB5MSk7XG4gIH1cblxuICB0aGlzLmVkZ2VzID0gZWRnZXM7XG4gIHRoaXMuY2VsbHMgPSBjZWxscztcblxuICBiZWFjaGVzID1cbiAgY2lyY2xlcyA9XG4gIGVkZ2VzID1cbiAgY2VsbHMgPSBudWxsO1xufVxuXG5EaWFncmFtLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IERpYWdyYW0sXG5cbiAgcG9seWdvbnM6IGZ1bmN0aW9uKCkge1xuICAgIHZhciBlZGdlcyA9IHRoaXMuZWRnZXM7XG5cbiAgICByZXR1cm4gdGhpcy5jZWxscy5tYXAoZnVuY3Rpb24oY2VsbCkge1xuICAgICAgdmFyIHBvbHlnb24gPSBjZWxsLmhhbGZlZGdlcy5tYXAoZnVuY3Rpb24oaSkgeyByZXR1cm4gY2VsbEhhbGZlZGdlU3RhcnQoY2VsbCwgZWRnZXNbaV0pOyB9KTtcbiAgICAgIHBvbHlnb24uZGF0YSA9IGNlbGwuc2l0ZS5kYXRhO1xuICAgICAgcmV0dXJuIHBvbHlnb247XG4gICAgfSk7XG4gIH0sXG5cbiAgdHJpYW5nbGVzOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdHJpYW5nbGVzID0gW10sXG4gICAgICAgIGVkZ2VzID0gdGhpcy5lZGdlcztcblxuICAgIHRoaXMuY2VsbHMuZm9yRWFjaChmdW5jdGlvbihjZWxsLCBpKSB7XG4gICAgICBpZiAoIShtID0gKGhhbGZlZGdlcyA9IGNlbGwuaGFsZmVkZ2VzKS5sZW5ndGgpKSByZXR1cm47XG4gICAgICB2YXIgc2l0ZSA9IGNlbGwuc2l0ZSxcbiAgICAgICAgICBoYWxmZWRnZXMsXG4gICAgICAgICAgaiA9IC0xLFxuICAgICAgICAgIG0sXG4gICAgICAgICAgczAsXG4gICAgICAgICAgZTEgPSBlZGdlc1toYWxmZWRnZXNbbSAtIDFdXSxcbiAgICAgICAgICBzMSA9IGUxLmxlZnQgPT09IHNpdGUgPyBlMS5yaWdodCA6IGUxLmxlZnQ7XG5cbiAgICAgIHdoaWxlICgrK2ogPCBtKSB7XG4gICAgICAgIHMwID0gczE7XG4gICAgICAgIGUxID0gZWRnZXNbaGFsZmVkZ2VzW2pdXTtcbiAgICAgICAgczEgPSBlMS5sZWZ0ID09PSBzaXRlID8gZTEucmlnaHQgOiBlMS5sZWZ0O1xuICAgICAgICBpZiAoczAgJiYgczEgJiYgaSA8IHMwLmluZGV4ICYmIGkgPCBzMS5pbmRleCAmJiB0cmlhbmdsZUFyZWEoc2l0ZSwgczAsIHMxKSA8IDApIHtcbiAgICAgICAgICB0cmlhbmdsZXMucHVzaChbc2l0ZS5kYXRhLCBzMC5kYXRhLCBzMS5kYXRhXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiB0cmlhbmdsZXM7XG4gIH0sXG5cbiAgbGlua3M6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmVkZ2VzLmZpbHRlcihmdW5jdGlvbihlZGdlKSB7XG4gICAgICByZXR1cm4gZWRnZS5yaWdodDtcbiAgICB9KS5tYXAoZnVuY3Rpb24oZWRnZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc291cmNlOiBlZGdlLmxlZnQuZGF0YSxcbiAgICAgICAgdGFyZ2V0OiBlZGdlLnJpZ2h0LmRhdGFcbiAgICAgIH07XG4gICAgfSk7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24oeCwgeSwgcmFkaXVzKSB7XG4gICAgdmFyIHRoYXQgPSB0aGlzLCBpMCwgaTEgPSB0aGF0Ll9mb3VuZCB8fCAwLCBuID0gdGhhdC5jZWxscy5sZW5ndGgsIGNlbGw7XG5cbiAgICAvLyBVc2UgdGhlIHByZXZpb3VzbHktZm91bmQgY2VsbCwgb3Igc3RhcnQgd2l0aCBhbiBhcmJpdHJhcnkgb25lLlxuICAgIHdoaWxlICghKGNlbGwgPSB0aGF0LmNlbGxzW2kxXSkpIGlmICgrK2kxID49IG4pIHJldHVybiBudWxsO1xuICAgIHZhciBkeCA9IHggLSBjZWxsLnNpdGVbMF0sIGR5ID0geSAtIGNlbGwuc2l0ZVsxXSwgZDIgPSBkeCAqIGR4ICsgZHkgKiBkeTtcblxuICAgIC8vIFRyYXZlcnNlIHRoZSBoYWxmLWVkZ2VzIHRvIGZpbmQgYSBjbG9zZXIgY2VsbCwgaWYgYW55LlxuICAgIGRvIHtcbiAgICAgIGNlbGwgPSB0aGF0LmNlbGxzW2kwID0gaTFdLCBpMSA9IG51bGw7XG4gICAgICBjZWxsLmhhbGZlZGdlcy5mb3JFYWNoKGZ1bmN0aW9uKGUpIHtcbiAgICAgICAgdmFyIGVkZ2UgPSB0aGF0LmVkZ2VzW2VdLCB2ID0gZWRnZS5sZWZ0O1xuICAgICAgICBpZiAoKHYgPT09IGNlbGwuc2l0ZSB8fCAhdikgJiYgISh2ID0gZWRnZS5yaWdodCkpIHJldHVybjtcbiAgICAgICAgdmFyIHZ4ID0geCAtIHZbMF0sIHZ5ID0geSAtIHZbMV0sIHYyID0gdnggKiB2eCArIHZ5ICogdnk7XG4gICAgICAgIGlmICh2MiA8IGQyKSBkMiA9IHYyLCBpMSA9IHYuaW5kZXg7XG4gICAgICB9KTtcbiAgICB9IHdoaWxlIChpMSAhPT0gbnVsbCk7XG5cbiAgICB0aGF0Ll9mb3VuZCA9IGkwO1xuXG4gICAgcmV0dXJuIHJhZGl1cyA9PSBudWxsIHx8IGQyIDw9IHJhZGl1cyAqIHJhZGl1cyA/IGNlbGwuc2l0ZSA6IG51bGw7XG4gIH1cbn07XG5cbnZhciB2b3Jvbm9pID0gZnVuY3Rpb24oKSB7XG4gIHZhciB4JCQxID0geCxcbiAgICAgIHkkJDEgPSB5LFxuICAgICAgZXh0ZW50ID0gbnVsbDtcblxuICBmdW5jdGlvbiB2b3Jvbm9pKGRhdGEpIHtcbiAgICByZXR1cm4gbmV3IERpYWdyYW0oZGF0YS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgICAgdmFyIHMgPSBbTWF0aC5yb3VuZCh4JCQxKGQsIGksIGRhdGEpIC8gZXBzaWxvbikgKiBlcHNpbG9uLCBNYXRoLnJvdW5kKHkkJDEoZCwgaSwgZGF0YSkgLyBlcHNpbG9uKSAqIGVwc2lsb25dO1xuICAgICAgcy5pbmRleCA9IGk7XG4gICAgICBzLmRhdGEgPSBkO1xuICAgICAgcmV0dXJuIHM7XG4gICAgfSksIGV4dGVudCk7XG4gIH1cblxuICB2b3Jvbm9pLnBvbHlnb25zID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIHJldHVybiB2b3Jvbm9pKGRhdGEpLnBvbHlnb25zKCk7XG4gIH07XG5cbiAgdm9yb25vaS5saW5rcyA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICByZXR1cm4gdm9yb25vaShkYXRhKS5saW5rcygpO1xuICB9O1xuXG4gIHZvcm9ub2kudHJpYW5nbGVzID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIHJldHVybiB2b3Jvbm9pKGRhdGEpLnRyaWFuZ2xlcygpO1xuICB9O1xuXG4gIHZvcm9ub2kueCA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh4JCQxID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCgrXyksIHZvcm9ub2kpIDogeCQkMTtcbiAgfTtcblxuICB2b3Jvbm9pLnkgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoeSQkMSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCB2b3Jvbm9pKSA6IHkkJDE7XG4gIH07XG5cbiAgdm9yb25vaS5leHRlbnQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZXh0ZW50ID0gXyA9PSBudWxsID8gbnVsbCA6IFtbK19bMF1bMF0sICtfWzBdWzFdXSwgWytfWzFdWzBdLCArX1sxXVsxXV1dLCB2b3Jvbm9pKSA6IGV4dGVudCAmJiBbW2V4dGVudFswXVswXSwgZXh0ZW50WzBdWzFdXSwgW2V4dGVudFsxXVswXSwgZXh0ZW50WzFdWzFdXV07XG4gIH07XG5cbiAgdm9yb25vaS5zaXplID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGV4dGVudCA9IF8gPT0gbnVsbCA/IG51bGwgOiBbWzAsIDBdLCBbK19bMF0sICtfWzFdXV0sIHZvcm9ub2kpIDogZXh0ZW50ICYmIFtleHRlbnRbMV1bMF0gLSBleHRlbnRbMF1bMF0sIGV4dGVudFsxXVsxXSAtIGV4dGVudFswXVsxXV07XG4gIH07XG5cbiAgcmV0dXJuIHZvcm9ub2k7XG59O1xuXG5leHBvcnRzLnZvcm9ub2kgPSB2b3Jvbm9pO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiLy8gaHR0cHM6Ly9kM2pzLm9yZy9kMy16b29tLyBWZXJzaW9uIDEuNy4xLiBDb3B5cmlnaHQgMjAxNyBNaWtlIEJvc3RvY2suXG4oZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBmYWN0b3J5KGV4cG9ydHMsIHJlcXVpcmUoJ2QzLWRpc3BhdGNoJyksIHJlcXVpcmUoJ2QzLWRyYWcnKSwgcmVxdWlyZSgnZDMtaW50ZXJwb2xhdGUnKSwgcmVxdWlyZSgnZDMtc2VsZWN0aW9uJyksIHJlcXVpcmUoJ2QzLXRyYW5zaXRpb24nKSkgOlxuXHR0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJywgJ2QzLWRpc3BhdGNoJywgJ2QzLWRyYWcnLCAnZDMtaW50ZXJwb2xhdGUnLCAnZDMtc2VsZWN0aW9uJywgJ2QzLXRyYW5zaXRpb24nXSwgZmFjdG9yeSkgOlxuXHQoZmFjdG9yeSgoZ2xvYmFsLmQzID0gZ2xvYmFsLmQzIHx8IHt9KSxnbG9iYWwuZDMsZ2xvYmFsLmQzLGdsb2JhbC5kMyxnbG9iYWwuZDMsZ2xvYmFsLmQzKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cyxkM0Rpc3BhdGNoLGQzRHJhZyxkM0ludGVycG9sYXRlLGQzU2VsZWN0aW9uLGQzVHJhbnNpdGlvbikgeyAndXNlIHN0cmljdCc7XG5cbnZhciBjb25zdGFudCA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB4O1xuICB9O1xufTtcblxuZnVuY3Rpb24gWm9vbUV2ZW50KHRhcmdldCwgdHlwZSwgdHJhbnNmb3JtKSB7XG4gIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICB0aGlzLnR5cGUgPSB0eXBlO1xuICB0aGlzLnRyYW5zZm9ybSA9IHRyYW5zZm9ybTtcbn1cblxuZnVuY3Rpb24gVHJhbnNmb3JtKGssIHgsIHkpIHtcbiAgdGhpcy5rID0gaztcbiAgdGhpcy54ID0geDtcbiAgdGhpcy55ID0geTtcbn1cblxuVHJhbnNmb3JtLnByb3RvdHlwZSA9IHtcbiAgY29uc3RydWN0b3I6IFRyYW5zZm9ybSxcbiAgc2NhbGU6IGZ1bmN0aW9uKGspIHtcbiAgICByZXR1cm4gayA9PT0gMSA/IHRoaXMgOiBuZXcgVHJhbnNmb3JtKHRoaXMuayAqIGssIHRoaXMueCwgdGhpcy55KTtcbiAgfSxcbiAgdHJhbnNsYXRlOiBmdW5jdGlvbih4LCB5KSB7XG4gICAgcmV0dXJuIHggPT09IDAgJiB5ID09PSAwID8gdGhpcyA6IG5ldyBUcmFuc2Zvcm0odGhpcy5rLCB0aGlzLnggKyB0aGlzLmsgKiB4LCB0aGlzLnkgKyB0aGlzLmsgKiB5KTtcbiAgfSxcbiAgYXBwbHk6IGZ1bmN0aW9uKHBvaW50KSB7XG4gICAgcmV0dXJuIFtwb2ludFswXSAqIHRoaXMuayArIHRoaXMueCwgcG9pbnRbMV0gKiB0aGlzLmsgKyB0aGlzLnldO1xuICB9LFxuICBhcHBseVg6IGZ1bmN0aW9uKHgpIHtcbiAgICByZXR1cm4geCAqIHRoaXMuayArIHRoaXMueDtcbiAgfSxcbiAgYXBwbHlZOiBmdW5jdGlvbih5KSB7XG4gICAgcmV0dXJuIHkgKiB0aGlzLmsgKyB0aGlzLnk7XG4gIH0sXG4gIGludmVydDogZnVuY3Rpb24obG9jYXRpb24pIHtcbiAgICByZXR1cm4gWyhsb2NhdGlvblswXSAtIHRoaXMueCkgLyB0aGlzLmssIChsb2NhdGlvblsxXSAtIHRoaXMueSkgLyB0aGlzLmtdO1xuICB9LFxuICBpbnZlcnRYOiBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuICh4IC0gdGhpcy54KSAvIHRoaXMuaztcbiAgfSxcbiAgaW52ZXJ0WTogZnVuY3Rpb24oeSkge1xuICAgIHJldHVybiAoeSAtIHRoaXMueSkgLyB0aGlzLms7XG4gIH0sXG4gIHJlc2NhbGVYOiBmdW5jdGlvbih4KSB7XG4gICAgcmV0dXJuIHguY29weSgpLmRvbWFpbih4LnJhbmdlKCkubWFwKHRoaXMuaW52ZXJ0WCwgdGhpcykubWFwKHguaW52ZXJ0LCB4KSk7XG4gIH0sXG4gIHJlc2NhbGVZOiBmdW5jdGlvbih5KSB7XG4gICAgcmV0dXJuIHkuY29weSgpLmRvbWFpbih5LnJhbmdlKCkubWFwKHRoaXMuaW52ZXJ0WSwgdGhpcykubWFwKHkuaW52ZXJ0LCB5KSk7XG4gIH0sXG4gIHRvU3RyaW5nOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gXCJ0cmFuc2xhdGUoXCIgKyB0aGlzLnggKyBcIixcIiArIHRoaXMueSArIFwiKSBzY2FsZShcIiArIHRoaXMuayArIFwiKVwiO1xuICB9XG59O1xuXG52YXIgaWRlbnRpdHkgPSBuZXcgVHJhbnNmb3JtKDEsIDAsIDApO1xuXG50cmFuc2Zvcm0ucHJvdG90eXBlID0gVHJhbnNmb3JtLnByb3RvdHlwZTtcblxuZnVuY3Rpb24gdHJhbnNmb3JtKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUuX196b29tIHx8IGlkZW50aXR5O1xufVxuXG5mdW5jdGlvbiBub3Byb3BhZ2F0aW9uKCkge1xuICBkM1NlbGVjdGlvbi5ldmVudC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbn1cblxudmFyIG5vZXZlbnQgPSBmdW5jdGlvbigpIHtcbiAgZDNTZWxlY3Rpb24uZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgZDNTZWxlY3Rpb24uZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG59O1xuXG4vLyBJZ25vcmUgcmlnaHQtY2xpY2ssIHNpbmNlIHRoYXQgc2hvdWxkIG9wZW4gdGhlIGNvbnRleHQgbWVudS5cbmZ1bmN0aW9uIGRlZmF1bHRGaWx0ZXIoKSB7XG4gIHJldHVybiAhZDNTZWxlY3Rpb24uZXZlbnQuYnV0dG9uO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0RXh0ZW50KCkge1xuICB2YXIgZSA9IHRoaXMsIHcsIGg7XG4gIGlmIChlIGluc3RhbmNlb2YgU1ZHRWxlbWVudCkge1xuICAgIGUgPSBlLm93bmVyU1ZHRWxlbWVudCB8fCBlO1xuICAgIHcgPSBlLndpZHRoLmJhc2VWYWwudmFsdWU7XG4gICAgaCA9IGUuaGVpZ2h0LmJhc2VWYWwudmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgdyA9IGUuY2xpZW50V2lkdGg7XG4gICAgaCA9IGUuY2xpZW50SGVpZ2h0O1xuICB9XG4gIHJldHVybiBbWzAsIDBdLCBbdywgaF1dO1xufVxuXG5mdW5jdGlvbiBkZWZhdWx0VHJhbnNmb3JtKCkge1xuICByZXR1cm4gdGhpcy5fX3pvb20gfHwgaWRlbnRpdHk7XG59XG5cbmZ1bmN0aW9uIGRlZmF1bHRXaGVlbERlbHRhKCkge1xuICByZXR1cm4gLWQzU2VsZWN0aW9uLmV2ZW50LmRlbHRhWSAqIChkM1NlbGVjdGlvbi5ldmVudC5kZWx0YU1vZGUgPyAxMjAgOiAxKSAvIDUwMDtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFRvdWNoYWJsZSgpIHtcbiAgcmV0dXJuIFwib250b3VjaHN0YXJ0XCIgaW4gdGhpcztcbn1cblxuZnVuY3Rpb24gZGVmYXVsdENvbnN0cmFpbih0cmFuc2Zvcm0kJDEsIGV4dGVudCwgdHJhbnNsYXRlRXh0ZW50KSB7XG4gIHZhciBkeDAgPSB0cmFuc2Zvcm0kJDEuaW52ZXJ0WChleHRlbnRbMF1bMF0pIC0gdHJhbnNsYXRlRXh0ZW50WzBdWzBdLFxuICAgICAgZHgxID0gdHJhbnNmb3JtJCQxLmludmVydFgoZXh0ZW50WzFdWzBdKSAtIHRyYW5zbGF0ZUV4dGVudFsxXVswXSxcbiAgICAgIGR5MCA9IHRyYW5zZm9ybSQkMS5pbnZlcnRZKGV4dGVudFswXVsxXSkgLSB0cmFuc2xhdGVFeHRlbnRbMF1bMV0sXG4gICAgICBkeTEgPSB0cmFuc2Zvcm0kJDEuaW52ZXJ0WShleHRlbnRbMV1bMV0pIC0gdHJhbnNsYXRlRXh0ZW50WzFdWzFdO1xuICByZXR1cm4gdHJhbnNmb3JtJCQxLnRyYW5zbGF0ZShcbiAgICBkeDEgPiBkeDAgPyAoZHgwICsgZHgxKSAvIDIgOiBNYXRoLm1pbigwLCBkeDApIHx8IE1hdGgubWF4KDAsIGR4MSksXG4gICAgZHkxID4gZHkwID8gKGR5MCArIGR5MSkgLyAyIDogTWF0aC5taW4oMCwgZHkwKSB8fCBNYXRoLm1heCgwLCBkeTEpXG4gICk7XG59XG5cbnZhciB6b29tID0gZnVuY3Rpb24oKSB7XG4gIHZhciBmaWx0ZXIgPSBkZWZhdWx0RmlsdGVyLFxuICAgICAgZXh0ZW50ID0gZGVmYXVsdEV4dGVudCxcbiAgICAgIGNvbnN0cmFpbiA9IGRlZmF1bHRDb25zdHJhaW4sXG4gICAgICB3aGVlbERlbHRhID0gZGVmYXVsdFdoZWVsRGVsdGEsXG4gICAgICB0b3VjaGFibGUgPSBkZWZhdWx0VG91Y2hhYmxlLFxuICAgICAgc2NhbGVFeHRlbnQgPSBbMCwgSW5maW5pdHldLFxuICAgICAgdHJhbnNsYXRlRXh0ZW50ID0gW1stSW5maW5pdHksIC1JbmZpbml0eV0sIFtJbmZpbml0eSwgSW5maW5pdHldXSxcbiAgICAgIGR1cmF0aW9uID0gMjUwLFxuICAgICAgaW50ZXJwb2xhdGUgPSBkM0ludGVycG9sYXRlLmludGVycG9sYXRlWm9vbSxcbiAgICAgIGdlc3R1cmVzID0gW10sXG4gICAgICBsaXN0ZW5lcnMgPSBkM0Rpc3BhdGNoLmRpc3BhdGNoKFwic3RhcnRcIiwgXCJ6b29tXCIsIFwiZW5kXCIpLFxuICAgICAgdG91Y2hzdGFydGluZyxcbiAgICAgIHRvdWNoZW5kaW5nLFxuICAgICAgdG91Y2hEZWxheSA9IDUwMCxcbiAgICAgIHdoZWVsRGVsYXkgPSAxNTAsXG4gICAgICBjbGlja0Rpc3RhbmNlMiA9IDA7XG5cbiAgZnVuY3Rpb24gem9vbShzZWxlY3Rpb24pIHtcbiAgICBzZWxlY3Rpb25cbiAgICAgICAgLnByb3BlcnR5KFwiX196b29tXCIsIGRlZmF1bHRUcmFuc2Zvcm0pXG4gICAgICAgIC5vbihcIndoZWVsLnpvb21cIiwgd2hlZWxlZClcbiAgICAgICAgLm9uKFwibW91c2Vkb3duLnpvb21cIiwgbW91c2Vkb3duZWQpXG4gICAgICAgIC5vbihcImRibGNsaWNrLnpvb21cIiwgZGJsY2xpY2tlZClcbiAgICAgIC5maWx0ZXIodG91Y2hhYmxlKVxuICAgICAgICAub24oXCJ0b3VjaHN0YXJ0Lnpvb21cIiwgdG91Y2hzdGFydGVkKVxuICAgICAgICAub24oXCJ0b3VjaG1vdmUuem9vbVwiLCB0b3VjaG1vdmVkKVxuICAgICAgICAub24oXCJ0b3VjaGVuZC56b29tIHRvdWNoY2FuY2VsLnpvb21cIiwgdG91Y2hlbmRlZClcbiAgICAgICAgLnN0eWxlKFwidG91Y2gtYWN0aW9uXCIsIFwibm9uZVwiKVxuICAgICAgICAuc3R5bGUoXCItd2Via2l0LXRhcC1oaWdobGlnaHQtY29sb3JcIiwgXCJyZ2JhKDAsMCwwLDApXCIpO1xuICB9XG5cbiAgem9vbS50cmFuc2Zvcm0gPSBmdW5jdGlvbihjb2xsZWN0aW9uLCB0cmFuc2Zvcm0kJDEpIHtcbiAgICB2YXIgc2VsZWN0aW9uID0gY29sbGVjdGlvbi5zZWxlY3Rpb24gPyBjb2xsZWN0aW9uLnNlbGVjdGlvbigpIDogY29sbGVjdGlvbjtcbiAgICBzZWxlY3Rpb24ucHJvcGVydHkoXCJfX3pvb21cIiwgZGVmYXVsdFRyYW5zZm9ybSk7XG4gICAgaWYgKGNvbGxlY3Rpb24gIT09IHNlbGVjdGlvbikge1xuICAgICAgc2NoZWR1bGUoY29sbGVjdGlvbiwgdHJhbnNmb3JtJCQxKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZWN0aW9uLmludGVycnVwdCgpLmVhY2goZnVuY3Rpb24oKSB7XG4gICAgICAgIGdlc3R1cmUodGhpcywgYXJndW1lbnRzKVxuICAgICAgICAgICAgLnN0YXJ0KClcbiAgICAgICAgICAgIC56b29tKG51bGwsIHR5cGVvZiB0cmFuc2Zvcm0kJDEgPT09IFwiZnVuY3Rpb25cIiA/IHRyYW5zZm9ybSQkMS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogdHJhbnNmb3JtJCQxKVxuICAgICAgICAgICAgLmVuZCgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9O1xuXG4gIHpvb20uc2NhbGVCeSA9IGZ1bmN0aW9uKHNlbGVjdGlvbiwgaykge1xuICAgIHpvb20uc2NhbGVUbyhzZWxlY3Rpb24sIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGswID0gdGhpcy5fX3pvb20uayxcbiAgICAgICAgICBrMSA9IHR5cGVvZiBrID09PSBcImZ1bmN0aW9uXCIgPyBrLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBrO1xuICAgICAgcmV0dXJuIGswICogazE7XG4gICAgfSk7XG4gIH07XG5cbiAgem9vbS5zY2FsZVRvID0gZnVuY3Rpb24oc2VsZWN0aW9uLCBrKSB7XG4gICAgem9vbS50cmFuc2Zvcm0oc2VsZWN0aW9uLCBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBlID0gZXh0ZW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgICAgdDAgPSB0aGlzLl9fem9vbSxcbiAgICAgICAgICBwMCA9IGNlbnRyb2lkKGUpLFxuICAgICAgICAgIHAxID0gdDAuaW52ZXJ0KHAwKSxcbiAgICAgICAgICBrMSA9IHR5cGVvZiBrID09PSBcImZ1bmN0aW9uXCIgPyBrLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgOiBrO1xuICAgICAgcmV0dXJuIGNvbnN0cmFpbih0cmFuc2xhdGUoc2NhbGUodDAsIGsxKSwgcDAsIHAxKSwgZSwgdHJhbnNsYXRlRXh0ZW50KTtcbiAgICB9KTtcbiAgfTtcblxuICB6b29tLnRyYW5zbGF0ZUJ5ID0gZnVuY3Rpb24oc2VsZWN0aW9uLCB4LCB5KSB7XG4gICAgem9vbS50cmFuc2Zvcm0oc2VsZWN0aW9uLCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBjb25zdHJhaW4odGhpcy5fX3pvb20udHJhbnNsYXRlKFxuICAgICAgICB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiID8geC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogeCxcbiAgICAgICAgdHlwZW9mIHkgPT09IFwiZnVuY3Rpb25cIiA/IHkuYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IHlcbiAgICAgICksIGV4dGVudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCB0cmFuc2xhdGVFeHRlbnQpO1xuICAgIH0pO1xuICB9O1xuXG4gIHpvb20udHJhbnNsYXRlVG8gPSBmdW5jdGlvbihzZWxlY3Rpb24sIHgsIHkpIHtcbiAgICB6b29tLnRyYW5zZm9ybShzZWxlY3Rpb24sIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGUgPSBleHRlbnQuYXBwbHkodGhpcywgYXJndW1lbnRzKSxcbiAgICAgICAgICB0ID0gdGhpcy5fX3pvb20sXG4gICAgICAgICAgcCA9IGNlbnRyb2lkKGUpO1xuICAgICAgcmV0dXJuIGNvbnN0cmFpbihpZGVudGl0eS50cmFuc2xhdGUocFswXSwgcFsxXSkuc2NhbGUodC5rKS50cmFuc2xhdGUoXG4gICAgICAgIHR5cGVvZiB4ID09PSBcImZ1bmN0aW9uXCIgPyAteC5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogLXgsXG4gICAgICAgIHR5cGVvZiB5ID09PSBcImZ1bmN0aW9uXCIgPyAteS5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDogLXlcbiAgICAgICksIGUsIHRyYW5zbGF0ZUV4dGVudCk7XG4gICAgfSk7XG4gIH07XG5cbiAgZnVuY3Rpb24gc2NhbGUodHJhbnNmb3JtJCQxLCBrKSB7XG4gICAgayA9IE1hdGgubWF4KHNjYWxlRXh0ZW50WzBdLCBNYXRoLm1pbihzY2FsZUV4dGVudFsxXSwgaykpO1xuICAgIHJldHVybiBrID09PSB0cmFuc2Zvcm0kJDEuayA/IHRyYW5zZm9ybSQkMSA6IG5ldyBUcmFuc2Zvcm0oaywgdHJhbnNmb3JtJCQxLngsIHRyYW5zZm9ybSQkMS55KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHRyYW5zbGF0ZSh0cmFuc2Zvcm0kJDEsIHAwLCBwMSkge1xuICAgIHZhciB4ID0gcDBbMF0gLSBwMVswXSAqIHRyYW5zZm9ybSQkMS5rLCB5ID0gcDBbMV0gLSBwMVsxXSAqIHRyYW5zZm9ybSQkMS5rO1xuICAgIHJldHVybiB4ID09PSB0cmFuc2Zvcm0kJDEueCAmJiB5ID09PSB0cmFuc2Zvcm0kJDEueSA/IHRyYW5zZm9ybSQkMSA6IG5ldyBUcmFuc2Zvcm0odHJhbnNmb3JtJCQxLmssIHgsIHkpO1xuICB9XG5cbiAgZnVuY3Rpb24gY2VudHJvaWQoZXh0ZW50KSB7XG4gICAgcmV0dXJuIFsoK2V4dGVudFswXVswXSArICtleHRlbnRbMV1bMF0pIC8gMiwgKCtleHRlbnRbMF1bMV0gKyArZXh0ZW50WzFdWzFdKSAvIDJdO1xuICB9XG5cbiAgZnVuY3Rpb24gc2NoZWR1bGUodHJhbnNpdGlvbiwgdHJhbnNmb3JtJCQxLCBjZW50ZXIpIHtcbiAgICB0cmFuc2l0aW9uXG4gICAgICAgIC5vbihcInN0YXJ0Lnpvb21cIiwgZnVuY3Rpb24oKSB7IGdlc3R1cmUodGhpcywgYXJndW1lbnRzKS5zdGFydCgpOyB9KVxuICAgICAgICAub24oXCJpbnRlcnJ1cHQuem9vbSBlbmQuem9vbVwiLCBmdW5jdGlvbigpIHsgZ2VzdHVyZSh0aGlzLCBhcmd1bWVudHMpLmVuZCgpOyB9KVxuICAgICAgICAudHdlZW4oXCJ6b29tXCIsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgIHZhciB0aGF0ID0gdGhpcyxcbiAgICAgICAgICAgICAgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAgICAgICAgZyA9IGdlc3R1cmUodGhhdCwgYXJncyksXG4gICAgICAgICAgICAgIGUgPSBleHRlbnQuYXBwbHkodGhhdCwgYXJncyksXG4gICAgICAgICAgICAgIHAgPSBjZW50ZXIgfHwgY2VudHJvaWQoZSksXG4gICAgICAgICAgICAgIHcgPSBNYXRoLm1heChlWzFdWzBdIC0gZVswXVswXSwgZVsxXVsxXSAtIGVbMF1bMV0pLFxuICAgICAgICAgICAgICBhID0gdGhhdC5fX3pvb20sXG4gICAgICAgICAgICAgIGIgPSB0eXBlb2YgdHJhbnNmb3JtJCQxID09PSBcImZ1bmN0aW9uXCIgPyB0cmFuc2Zvcm0kJDEuYXBwbHkodGhhdCwgYXJncykgOiB0cmFuc2Zvcm0kJDEsXG4gICAgICAgICAgICAgIGkgPSBpbnRlcnBvbGF0ZShhLmludmVydChwKS5jb25jYXQodyAvIGEuayksIGIuaW52ZXJ0KHApLmNvbmNhdCh3IC8gYi5rKSk7XG4gICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgIGlmICh0ID09PSAxKSB0ID0gYjsgLy8gQXZvaWQgcm91bmRpbmcgZXJyb3Igb24gZW5kLlxuICAgICAgICAgICAgZWxzZSB7IHZhciBsID0gaSh0KSwgayA9IHcgLyBsWzJdOyB0ID0gbmV3IFRyYW5zZm9ybShrLCBwWzBdIC0gbFswXSAqIGssIHBbMV0gLSBsWzFdICogayk7IH1cbiAgICAgICAgICAgIGcuem9vbShudWxsLCB0KTtcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdlc3R1cmUodGhhdCwgYXJncykge1xuICAgIGZvciAodmFyIGkgPSAwLCBuID0gZ2VzdHVyZXMubGVuZ3RoLCBnOyBpIDwgbjsgKytpKSB7XG4gICAgICBpZiAoKGcgPSBnZXN0dXJlc1tpXSkudGhhdCA9PT0gdGhhdCkge1xuICAgICAgICByZXR1cm4gZztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBHZXN0dXJlKHRoYXQsIGFyZ3MpO1xuICB9XG5cbiAgZnVuY3Rpb24gR2VzdHVyZSh0aGF0LCBhcmdzKSB7XG4gICAgdGhpcy50aGF0ID0gdGhhdDtcbiAgICB0aGlzLmFyZ3MgPSBhcmdzO1xuICAgIHRoaXMuaW5kZXggPSAtMTtcbiAgICB0aGlzLmFjdGl2ZSA9IDA7XG4gICAgdGhpcy5leHRlbnQgPSBleHRlbnQuYXBwbHkodGhhdCwgYXJncyk7XG4gIH1cblxuICBHZXN0dXJlLnByb3RvdHlwZSA9IHtcbiAgICBzdGFydDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoKyt0aGlzLmFjdGl2ZSA9PT0gMSkge1xuICAgICAgICB0aGlzLmluZGV4ID0gZ2VzdHVyZXMucHVzaCh0aGlzKSAtIDE7XG4gICAgICAgIHRoaXMuZW1pdChcInN0YXJ0XCIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICB6b29tOiBmdW5jdGlvbihrZXksIHRyYW5zZm9ybSQkMSkge1xuICAgICAgaWYgKHRoaXMubW91c2UgJiYga2V5ICE9PSBcIm1vdXNlXCIpIHRoaXMubW91c2VbMV0gPSB0cmFuc2Zvcm0kJDEuaW52ZXJ0KHRoaXMubW91c2VbMF0pO1xuICAgICAgaWYgKHRoaXMudG91Y2gwICYmIGtleSAhPT0gXCJ0b3VjaFwiKSB0aGlzLnRvdWNoMFsxXSA9IHRyYW5zZm9ybSQkMS5pbnZlcnQodGhpcy50b3VjaDBbMF0pO1xuICAgICAgaWYgKHRoaXMudG91Y2gxICYmIGtleSAhPT0gXCJ0b3VjaFwiKSB0aGlzLnRvdWNoMVsxXSA9IHRyYW5zZm9ybSQkMS5pbnZlcnQodGhpcy50b3VjaDFbMF0pO1xuICAgICAgdGhpcy50aGF0Ll9fem9vbSA9IHRyYW5zZm9ybSQkMTtcbiAgICAgIHRoaXMuZW1pdChcInpvb21cIik7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIGVuZDogZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoLS10aGlzLmFjdGl2ZSA9PT0gMCkge1xuICAgICAgICBnZXN0dXJlcy5zcGxpY2UodGhpcy5pbmRleCwgMSk7XG4gICAgICAgIHRoaXMuaW5kZXggPSAtMTtcbiAgICAgICAgdGhpcy5lbWl0KFwiZW5kXCIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBlbWl0OiBmdW5jdGlvbih0eXBlKSB7XG4gICAgICBkM1NlbGVjdGlvbi5jdXN0b21FdmVudChuZXcgWm9vbUV2ZW50KHpvb20sIHR5cGUsIHRoaXMudGhhdC5fX3pvb20pLCBsaXN0ZW5lcnMuYXBwbHksIGxpc3RlbmVycywgW3R5cGUsIHRoaXMudGhhdCwgdGhpcy5hcmdzXSk7XG4gICAgfVxuICB9O1xuXG4gIGZ1bmN0aW9uIHdoZWVsZWQoKSB7XG4gICAgaWYgKCFmaWx0ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSkgcmV0dXJuO1xuICAgIHZhciBnID0gZ2VzdHVyZSh0aGlzLCBhcmd1bWVudHMpLFxuICAgICAgICB0ID0gdGhpcy5fX3pvb20sXG4gICAgICAgIGsgPSBNYXRoLm1heChzY2FsZUV4dGVudFswXSwgTWF0aC5taW4oc2NhbGVFeHRlbnRbMV0sIHQuayAqIE1hdGgucG93KDIsIHdoZWVsRGVsdGEuYXBwbHkodGhpcywgYXJndW1lbnRzKSkpKSxcbiAgICAgICAgcCA9IGQzU2VsZWN0aW9uLm1vdXNlKHRoaXMpO1xuXG4gICAgLy8gSWYgdGhlIG1vdXNlIGlzIGluIHRoZSBzYW1lIGxvY2F0aW9uIGFzIGJlZm9yZSwgcmV1c2UgaXQuXG4gICAgLy8gSWYgdGhlcmUgd2VyZSByZWNlbnQgd2hlZWwgZXZlbnRzLCByZXNldCB0aGUgd2hlZWwgaWRsZSB0aW1lb3V0LlxuICAgIGlmIChnLndoZWVsKSB7XG4gICAgICBpZiAoZy5tb3VzZVswXVswXSAhPT0gcFswXSB8fCBnLm1vdXNlWzBdWzFdICE9PSBwWzFdKSB7XG4gICAgICAgIGcubW91c2VbMV0gPSB0LmludmVydChnLm1vdXNlWzBdID0gcCk7XG4gICAgICB9XG4gICAgICBjbGVhclRpbWVvdXQoZy53aGVlbCk7XG4gICAgfVxuXG4gICAgLy8gSWYgdGhpcyB3aGVlbCBldmVudCB3b27igJl0IHRyaWdnZXIgYSB0cmFuc2Zvcm0gY2hhbmdlLCBpZ25vcmUgaXQuXG4gICAgZWxzZSBpZiAodC5rID09PSBrKSByZXR1cm47XG5cbiAgICAvLyBPdGhlcndpc2UsIGNhcHR1cmUgdGhlIG1vdXNlIHBvaW50IGFuZCBsb2NhdGlvbiBhdCB0aGUgc3RhcnQuXG4gICAgZWxzZSB7XG4gICAgICBnLm1vdXNlID0gW3AsIHQuaW52ZXJ0KHApXTtcbiAgICAgIGQzVHJhbnNpdGlvbi5pbnRlcnJ1cHQodGhpcyk7XG4gICAgICBnLnN0YXJ0KCk7XG4gICAgfVxuXG4gICAgbm9ldmVudCgpO1xuICAgIGcud2hlZWwgPSBzZXRUaW1lb3V0KHdoZWVsaWRsZWQsIHdoZWVsRGVsYXkpO1xuICAgIGcuem9vbShcIm1vdXNlXCIsIGNvbnN0cmFpbih0cmFuc2xhdGUoc2NhbGUodCwgayksIGcubW91c2VbMF0sIGcubW91c2VbMV0pLCBnLmV4dGVudCwgdHJhbnNsYXRlRXh0ZW50KSk7XG5cbiAgICBmdW5jdGlvbiB3aGVlbGlkbGVkKCkge1xuICAgICAgZy53aGVlbCA9IG51bGw7XG4gICAgICBnLmVuZCgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG1vdXNlZG93bmVkKCkge1xuICAgIGlmICh0b3VjaGVuZGluZyB8fCAhZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpIHJldHVybjtcbiAgICB2YXIgZyA9IGdlc3R1cmUodGhpcywgYXJndW1lbnRzKSxcbiAgICAgICAgdiA9IGQzU2VsZWN0aW9uLnNlbGVjdChkM1NlbGVjdGlvbi5ldmVudC52aWV3KS5vbihcIm1vdXNlbW92ZS56b29tXCIsIG1vdXNlbW92ZWQsIHRydWUpLm9uKFwibW91c2V1cC56b29tXCIsIG1vdXNldXBwZWQsIHRydWUpLFxuICAgICAgICBwID0gZDNTZWxlY3Rpb24ubW91c2UodGhpcyksXG4gICAgICAgIHgwID0gZDNTZWxlY3Rpb24uZXZlbnQuY2xpZW50WCxcbiAgICAgICAgeTAgPSBkM1NlbGVjdGlvbi5ldmVudC5jbGllbnRZO1xuXG4gICAgZDNEcmFnLmRyYWdEaXNhYmxlKGQzU2VsZWN0aW9uLmV2ZW50LnZpZXcpO1xuICAgIG5vcHJvcGFnYXRpb24oKTtcbiAgICBnLm1vdXNlID0gW3AsIHRoaXMuX196b29tLmludmVydChwKV07XG4gICAgZDNUcmFuc2l0aW9uLmludGVycnVwdCh0aGlzKTtcbiAgICBnLnN0YXJ0KCk7XG5cbiAgICBmdW5jdGlvbiBtb3VzZW1vdmVkKCkge1xuICAgICAgbm9ldmVudCgpO1xuICAgICAgaWYgKCFnLm1vdmVkKSB7XG4gICAgICAgIHZhciBkeCA9IGQzU2VsZWN0aW9uLmV2ZW50LmNsaWVudFggLSB4MCwgZHkgPSBkM1NlbGVjdGlvbi5ldmVudC5jbGllbnRZIC0geTA7XG4gICAgICAgIGcubW92ZWQgPSBkeCAqIGR4ICsgZHkgKiBkeSA+IGNsaWNrRGlzdGFuY2UyO1xuICAgICAgfVxuICAgICAgZy56b29tKFwibW91c2VcIiwgY29uc3RyYWluKHRyYW5zbGF0ZShnLnRoYXQuX196b29tLCBnLm1vdXNlWzBdID0gZDNTZWxlY3Rpb24ubW91c2UoZy50aGF0KSwgZy5tb3VzZVsxXSksIGcuZXh0ZW50LCB0cmFuc2xhdGVFeHRlbnQpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb3VzZXVwcGVkKCkge1xuICAgICAgdi5vbihcIm1vdXNlbW92ZS56b29tIG1vdXNldXAuem9vbVwiLCBudWxsKTtcbiAgICAgIGQzRHJhZy5kcmFnRW5hYmxlKGQzU2VsZWN0aW9uLmV2ZW50LnZpZXcsIGcubW92ZWQpO1xuICAgICAgbm9ldmVudCgpO1xuICAgICAgZy5lbmQoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBkYmxjbGlja2VkKCkge1xuICAgIGlmICghZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpIHJldHVybjtcbiAgICB2YXIgdDAgPSB0aGlzLl9fem9vbSxcbiAgICAgICAgcDAgPSBkM1NlbGVjdGlvbi5tb3VzZSh0aGlzKSxcbiAgICAgICAgcDEgPSB0MC5pbnZlcnQocDApLFxuICAgICAgICBrMSA9IHQwLmsgKiAoZDNTZWxlY3Rpb24uZXZlbnQuc2hpZnRLZXkgPyAwLjUgOiAyKSxcbiAgICAgICAgdDEgPSBjb25zdHJhaW4odHJhbnNsYXRlKHNjYWxlKHQwLCBrMSksIHAwLCBwMSksIGV4dGVudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpLCB0cmFuc2xhdGVFeHRlbnQpO1xuXG4gICAgbm9ldmVudCgpO1xuICAgIGlmIChkdXJhdGlvbiA+IDApIGQzU2VsZWN0aW9uLnNlbGVjdCh0aGlzKS50cmFuc2l0aW9uKCkuZHVyYXRpb24oZHVyYXRpb24pLmNhbGwoc2NoZWR1bGUsIHQxLCBwMCk7XG4gICAgZWxzZSBkM1NlbGVjdGlvbi5zZWxlY3QodGhpcykuY2FsbCh6b29tLnRyYW5zZm9ybSwgdDEpO1xuICB9XG5cbiAgZnVuY3Rpb24gdG91Y2hzdGFydGVkKCkge1xuICAgIGlmICghZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpIHJldHVybjtcbiAgICB2YXIgZyA9IGdlc3R1cmUodGhpcywgYXJndW1lbnRzKSxcbiAgICAgICAgdG91Y2hlcyA9IGQzU2VsZWN0aW9uLmV2ZW50LmNoYW5nZWRUb3VjaGVzLFxuICAgICAgICBzdGFydGVkLFxuICAgICAgICBuID0gdG91Y2hlcy5sZW5ndGgsIGksIHQsIHA7XG5cbiAgICBub3Byb3BhZ2F0aW9uKCk7XG4gICAgZm9yIChpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgdCA9IHRvdWNoZXNbaV0sIHAgPSBkM1NlbGVjdGlvbi50b3VjaCh0aGlzLCB0b3VjaGVzLCB0LmlkZW50aWZpZXIpO1xuICAgICAgcCA9IFtwLCB0aGlzLl9fem9vbS5pbnZlcnQocCksIHQuaWRlbnRpZmllcl07XG4gICAgICBpZiAoIWcudG91Y2gwKSBnLnRvdWNoMCA9IHAsIHN0YXJ0ZWQgPSB0cnVlO1xuICAgICAgZWxzZSBpZiAoIWcudG91Y2gxKSBnLnRvdWNoMSA9IHA7XG4gICAgfVxuXG4gICAgLy8gSWYgdGhpcyBpcyBhIGRibHRhcCwgcmVyb3V0ZSB0byB0aGUgKG9wdGlvbmFsKSBkYmxjbGljay56b29tIGhhbmRsZXIuXG4gICAgaWYgKHRvdWNoc3RhcnRpbmcpIHtcbiAgICAgIHRvdWNoc3RhcnRpbmcgPSBjbGVhclRpbWVvdXQodG91Y2hzdGFydGluZyk7XG4gICAgICBpZiAoIWcudG91Y2gxKSB7XG4gICAgICAgIGcuZW5kKCk7XG4gICAgICAgIHAgPSBkM1NlbGVjdGlvbi5zZWxlY3QodGhpcykub24oXCJkYmxjbGljay56b29tXCIpO1xuICAgICAgICBpZiAocCkgcC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHN0YXJ0ZWQpIHtcbiAgICAgIHRvdWNoc3RhcnRpbmcgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyB0b3VjaHN0YXJ0aW5nID0gbnVsbDsgfSwgdG91Y2hEZWxheSk7XG4gICAgICBkM1RyYW5zaXRpb24uaW50ZXJydXB0KHRoaXMpO1xuICAgICAgZy5zdGFydCgpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIHRvdWNobW92ZWQoKSB7XG4gICAgdmFyIGcgPSBnZXN0dXJlKHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgIHRvdWNoZXMgPSBkM1NlbGVjdGlvbi5ldmVudC5jaGFuZ2VkVG91Y2hlcyxcbiAgICAgICAgbiA9IHRvdWNoZXMubGVuZ3RoLCBpLCB0LCBwLCBsO1xuXG4gICAgbm9ldmVudCgpO1xuICAgIGlmICh0b3VjaHN0YXJ0aW5nKSB0b3VjaHN0YXJ0aW5nID0gY2xlYXJUaW1lb3V0KHRvdWNoc3RhcnRpbmcpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBuOyArK2kpIHtcbiAgICAgIHQgPSB0b3VjaGVzW2ldLCBwID0gZDNTZWxlY3Rpb24udG91Y2godGhpcywgdG91Y2hlcywgdC5pZGVudGlmaWVyKTtcbiAgICAgIGlmIChnLnRvdWNoMCAmJiBnLnRvdWNoMFsyXSA9PT0gdC5pZGVudGlmaWVyKSBnLnRvdWNoMFswXSA9IHA7XG4gICAgICBlbHNlIGlmIChnLnRvdWNoMSAmJiBnLnRvdWNoMVsyXSA9PT0gdC5pZGVudGlmaWVyKSBnLnRvdWNoMVswXSA9IHA7XG4gICAgfVxuICAgIHQgPSBnLnRoYXQuX196b29tO1xuICAgIGlmIChnLnRvdWNoMSkge1xuICAgICAgdmFyIHAwID0gZy50b3VjaDBbMF0sIGwwID0gZy50b3VjaDBbMV0sXG4gICAgICAgICAgcDEgPSBnLnRvdWNoMVswXSwgbDEgPSBnLnRvdWNoMVsxXSxcbiAgICAgICAgICBkcCA9IChkcCA9IHAxWzBdIC0gcDBbMF0pICogZHAgKyAoZHAgPSBwMVsxXSAtIHAwWzFdKSAqIGRwLFxuICAgICAgICAgIGRsID0gKGRsID0gbDFbMF0gLSBsMFswXSkgKiBkbCArIChkbCA9IGwxWzFdIC0gbDBbMV0pICogZGw7XG4gICAgICB0ID0gc2NhbGUodCwgTWF0aC5zcXJ0KGRwIC8gZGwpKTtcbiAgICAgIHAgPSBbKHAwWzBdICsgcDFbMF0pIC8gMiwgKHAwWzFdICsgcDFbMV0pIC8gMl07XG4gICAgICBsID0gWyhsMFswXSArIGwxWzBdKSAvIDIsIChsMFsxXSArIGwxWzFdKSAvIDJdO1xuICAgIH1cbiAgICBlbHNlIGlmIChnLnRvdWNoMCkgcCA9IGcudG91Y2gwWzBdLCBsID0gZy50b3VjaDBbMV07XG4gICAgZWxzZSByZXR1cm47XG4gICAgZy56b29tKFwidG91Y2hcIiwgY29uc3RyYWluKHRyYW5zbGF0ZSh0LCBwLCBsKSwgZy5leHRlbnQsIHRyYW5zbGF0ZUV4dGVudCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdG91Y2hlbmRlZCgpIHtcbiAgICB2YXIgZyA9IGdlc3R1cmUodGhpcywgYXJndW1lbnRzKSxcbiAgICAgICAgdG91Y2hlcyA9IGQzU2VsZWN0aW9uLmV2ZW50LmNoYW5nZWRUb3VjaGVzLFxuICAgICAgICBuID0gdG91Y2hlcy5sZW5ndGgsIGksIHQ7XG5cbiAgICBub3Byb3BhZ2F0aW9uKCk7XG4gICAgaWYgKHRvdWNoZW5kaW5nKSBjbGVhclRpbWVvdXQodG91Y2hlbmRpbmcpO1xuICAgIHRvdWNoZW5kaW5nID0gc2V0VGltZW91dChmdW5jdGlvbigpIHsgdG91Y2hlbmRpbmcgPSBudWxsOyB9LCB0b3VjaERlbGF5KTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICB0ID0gdG91Y2hlc1tpXTtcbiAgICAgIGlmIChnLnRvdWNoMCAmJiBnLnRvdWNoMFsyXSA9PT0gdC5pZGVudGlmaWVyKSBkZWxldGUgZy50b3VjaDA7XG4gICAgICBlbHNlIGlmIChnLnRvdWNoMSAmJiBnLnRvdWNoMVsyXSA9PT0gdC5pZGVudGlmaWVyKSBkZWxldGUgZy50b3VjaDE7XG4gICAgfVxuICAgIGlmIChnLnRvdWNoMSAmJiAhZy50b3VjaDApIGcudG91Y2gwID0gZy50b3VjaDEsIGRlbGV0ZSBnLnRvdWNoMTtcbiAgICBpZiAoZy50b3VjaDApIGcudG91Y2gwWzFdID0gdGhpcy5fX3pvb20uaW52ZXJ0KGcudG91Y2gwWzBdKTtcbiAgICBlbHNlIGcuZW5kKCk7XG4gIH1cblxuICB6b29tLndoZWVsRGVsdGEgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAod2hlZWxEZWx0YSA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoK18pLCB6b29tKSA6IHdoZWVsRGVsdGE7XG4gIH07XG5cbiAgem9vbS5maWx0ZXIgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZmlsdGVyID0gdHlwZW9mIF8gPT09IFwiZnVuY3Rpb25cIiA/IF8gOiBjb25zdGFudCghIV8pLCB6b29tKSA6IGZpbHRlcjtcbiAgfTtcblxuICB6b29tLnRvdWNoYWJsZSA9IGZ1bmN0aW9uKF8pIHtcbiAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA/ICh0b3VjaGFibGUgPSB0eXBlb2YgXyA9PT0gXCJmdW5jdGlvblwiID8gXyA6IGNvbnN0YW50KCEhXyksIHpvb20pIDogdG91Y2hhYmxlO1xuICB9O1xuXG4gIHpvb20uZXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGV4dGVudCA9IHR5cGVvZiBfID09PSBcImZ1bmN0aW9uXCIgPyBfIDogY29uc3RhbnQoW1srX1swXVswXSwgK19bMF1bMV1dLCBbK19bMV1bMF0sICtfWzFdWzFdXV0pLCB6b29tKSA6IGV4dGVudDtcbiAgfTtcblxuICB6b29tLnNjYWxlRXh0ZW50ID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKHNjYWxlRXh0ZW50WzBdID0gK19bMF0sIHNjYWxlRXh0ZW50WzFdID0gK19bMV0sIHpvb20pIDogW3NjYWxlRXh0ZW50WzBdLCBzY2FsZUV4dGVudFsxXV07XG4gIH07XG5cbiAgem9vbS50cmFuc2xhdGVFeHRlbnQgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAodHJhbnNsYXRlRXh0ZW50WzBdWzBdID0gK19bMF1bMF0sIHRyYW5zbGF0ZUV4dGVudFsxXVswXSA9ICtfWzFdWzBdLCB0cmFuc2xhdGVFeHRlbnRbMF1bMV0gPSArX1swXVsxXSwgdHJhbnNsYXRlRXh0ZW50WzFdWzFdID0gK19bMV1bMV0sIHpvb20pIDogW1t0cmFuc2xhdGVFeHRlbnRbMF1bMF0sIHRyYW5zbGF0ZUV4dGVudFswXVsxXV0sIFt0cmFuc2xhdGVFeHRlbnRbMV1bMF0sIHRyYW5zbGF0ZUV4dGVudFsxXVsxXV1dO1xuICB9O1xuXG4gIHpvb20uY29uc3RyYWluID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGNvbnN0cmFpbiA9IF8sIHpvb20pIDogY29uc3RyYWluO1xuICB9O1xuXG4gIHpvb20uZHVyYXRpb24gPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoZHVyYXRpb24gPSArXywgem9vbSkgOiBkdXJhdGlvbjtcbiAgfTtcblxuICB6b29tLmludGVycG9sYXRlID0gZnVuY3Rpb24oXykge1xuICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID8gKGludGVycG9sYXRlID0gXywgem9vbSkgOiBpbnRlcnBvbGF0ZTtcbiAgfTtcblxuICB6b29tLm9uID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIHZhbHVlID0gbGlzdGVuZXJzLm9uLmFwcGx5KGxpc3RlbmVycywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gdmFsdWUgPT09IGxpc3RlbmVycyA/IHpvb20gOiB2YWx1ZTtcbiAgfTtcblxuICB6b29tLmNsaWNrRGlzdGFuY2UgPSBmdW5jdGlvbihfKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPyAoY2xpY2tEaXN0YW5jZTIgPSAoXyA9ICtfKSAqIF8sIHpvb20pIDogTWF0aC5zcXJ0KGNsaWNrRGlzdGFuY2UyKTtcbiAgfTtcblxuICByZXR1cm4gem9vbTtcbn07XG5cbmV4cG9ydHMuem9vbSA9IHpvb207XG5leHBvcnRzLnpvb21UcmFuc2Zvcm0gPSB0cmFuc2Zvcm07XG5leHBvcnRzLnpvb21JZGVudGl0eSA9IGlkZW50aXR5O1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG52YXIgZDNBcnJheSA9IHJlcXVpcmUoJ2QzLWFycmF5Jyk7XG52YXIgZDNBeGlzID0gcmVxdWlyZSgnZDMtYXhpcycpO1xudmFyIGQzQnJ1c2ggPSByZXF1aXJlKCdkMy1icnVzaCcpO1xudmFyIGQzQ2hvcmQgPSByZXF1aXJlKCdkMy1jaG9yZCcpO1xudmFyIGQzQ29sbGVjdGlvbiA9IHJlcXVpcmUoJ2QzLWNvbGxlY3Rpb24nKTtcbnZhciBkM0NvbG9yID0gcmVxdWlyZSgnZDMtY29sb3InKTtcbnZhciBkM0Rpc3BhdGNoID0gcmVxdWlyZSgnZDMtZGlzcGF0Y2gnKTtcbnZhciBkM0RyYWcgPSByZXF1aXJlKCdkMy1kcmFnJyk7XG52YXIgZDNEc3YgPSByZXF1aXJlKCdkMy1kc3YnKTtcbnZhciBkM0Vhc2UgPSByZXF1aXJlKCdkMy1lYXNlJyk7XG52YXIgZDNGb3JjZSA9IHJlcXVpcmUoJ2QzLWZvcmNlJyk7XG52YXIgZDNGb3JtYXQgPSByZXF1aXJlKCdkMy1mb3JtYXQnKTtcbnZhciBkM0dlbyA9IHJlcXVpcmUoJ2QzLWdlbycpO1xudmFyIGQzSGllcmFyY2h5ID0gcmVxdWlyZSgnZDMtaGllcmFyY2h5Jyk7XG52YXIgZDNJbnRlcnBvbGF0ZSA9IHJlcXVpcmUoJ2QzLWludGVycG9sYXRlJyk7XG52YXIgZDNQYXRoID0gcmVxdWlyZSgnZDMtcGF0aCcpO1xudmFyIGQzUG9seWdvbiA9IHJlcXVpcmUoJ2QzLXBvbHlnb24nKTtcbnZhciBkM1F1YWR0cmVlID0gcmVxdWlyZSgnZDMtcXVhZHRyZWUnKTtcbnZhciBkM1F1ZXVlID0gcmVxdWlyZSgnZDMtcXVldWUnKTtcbnZhciBkM1JhbmRvbSA9IHJlcXVpcmUoJ2QzLXJhbmRvbScpO1xudmFyIGQzUmVxdWVzdCA9IHJlcXVpcmUoJ2QzLXJlcXVlc3QnKTtcbnZhciBkM1NjYWxlID0gcmVxdWlyZSgnZDMtc2NhbGUnKTtcbnZhciBkM1NlbGVjdGlvbiA9IHJlcXVpcmUoJ2QzLXNlbGVjdGlvbicpO1xudmFyIGQzU2hhcGUgPSByZXF1aXJlKCdkMy1zaGFwZScpO1xudmFyIGQzVGltZSA9IHJlcXVpcmUoJ2QzLXRpbWUnKTtcbnZhciBkM1RpbWVGb3JtYXQgPSByZXF1aXJlKCdkMy10aW1lLWZvcm1hdCcpO1xudmFyIGQzVGltZXIgPSByZXF1aXJlKCdkMy10aW1lcicpO1xudmFyIGQzVHJhbnNpdGlvbiA9IHJlcXVpcmUoJ2QzLXRyYW5zaXRpb24nKTtcbnZhciBkM1Zvcm9ub2kgPSByZXF1aXJlKCdkMy12b3Jvbm9pJyk7XG52YXIgZDNab29tID0gcmVxdWlyZSgnZDMtem9vbScpO1xuXG52YXIgdmVyc2lvbiA9IFwiNC4xMy4wXCI7XG5cbmV4cG9ydHMudmVyc2lvbiA9IHZlcnNpb247XG5PYmplY3Qua2V5cyhkM0FycmF5KS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgZXhwb3J0c1trZXldID0gZDNBcnJheVtrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzQXhpcykuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IGV4cG9ydHNba2V5XSA9IGQzQXhpc1trZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzQnJ1c2gpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM0JydXNoW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNDaG9yZCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IGV4cG9ydHNba2V5XSA9IGQzQ2hvcmRba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM0NvbGxlY3Rpb24pLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM0NvbGxlY3Rpb25ba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM0NvbG9yKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgZXhwb3J0c1trZXldID0gZDNDb2xvcltrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzRGlzcGF0Y2gpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM0Rpc3BhdGNoW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNEcmFnKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgZXhwb3J0c1trZXldID0gZDNEcmFnW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNEc3YpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM0RzdltrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzRWFzZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IGV4cG9ydHNba2V5XSA9IGQzRWFzZVtrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzRm9yY2UpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM0ZvcmNlW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNGb3JtYXQpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM0Zvcm1hdFtrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzR2VvKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgZXhwb3J0c1trZXldID0gZDNHZW9ba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM0hpZXJhcmNoeSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IGV4cG9ydHNba2V5XSA9IGQzSGllcmFyY2h5W2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNJbnRlcnBvbGF0ZSkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IGV4cG9ydHNba2V5XSA9IGQzSW50ZXJwb2xhdGVba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM1BhdGgpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1BhdGhba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM1BvbHlnb24pLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1BvbHlnb25ba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM1F1YWR0cmVlKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgZXhwb3J0c1trZXldID0gZDNRdWFkdHJlZVtrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzUXVldWUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1F1ZXVlW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNSYW5kb20pLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1JhbmRvbVtrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzUmVxdWVzdCkuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IGV4cG9ydHNba2V5XSA9IGQzUmVxdWVzdFtrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzU2NhbGUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1NjYWxlW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNTZWxlY3Rpb24pLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1NlbGVjdGlvbltrZXldOyB9KTtcbk9iamVjdC5rZXlzKGQzU2hhcGUpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1NoYXBlW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNUaW1lKS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgZXhwb3J0c1trZXldID0gZDNUaW1lW2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNUaW1lRm9ybWF0KS5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHsgZXhwb3J0c1trZXldID0gZDNUaW1lRm9ybWF0W2tleV07IH0pO1xuT2JqZWN0LmtleXMoZDNUaW1lcikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7IGV4cG9ydHNba2V5XSA9IGQzVGltZXJba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM1RyYW5zaXRpb24pLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1RyYW5zaXRpb25ba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM1Zvcm9ub2kpLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1Zvcm9ub2lba2V5XTsgfSk7XG5PYmplY3Qua2V5cyhkM1pvb20pLmZvckVhY2goZnVuY3Rpb24gKGtleSkgeyBleHBvcnRzW2tleV0gPSBkM1pvb21ba2V5XTsgfSk7XG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJldmVudFwiLCB7Z2V0OiBmdW5jdGlvbigpIHsgcmV0dXJuIGQzU2VsZWN0aW9uLmV2ZW50OyB9fSk7XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCkge1xuICB0aGlzLl9ldmVudHMgPSB0aGlzLl9ldmVudHMgfHwge307XG4gIHRoaXMuX21heExpc3RlbmVycyA9IHRoaXMuX21heExpc3RlbmVycyB8fCB1bmRlZmluZWQ7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50RW1pdHRlcjtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC4xMC54XG5FdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyID0gRXZlbnRFbWl0dGVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHMgPSB1bmRlZmluZWQ7XG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLl9tYXhMaXN0ZW5lcnMgPSB1bmRlZmluZWQ7XG5cbi8vIEJ5IGRlZmF1bHQgRXZlbnRFbWl0dGVycyB3aWxsIHByaW50IGEgd2FybmluZyBpZiBtb3JlIHRoYW4gMTAgbGlzdGVuZXJzIGFyZVxuLy8gYWRkZWQgdG8gaXQuIFRoaXMgaXMgYSB1c2VmdWwgZGVmYXVsdCB3aGljaCBoZWxwcyBmaW5kaW5nIG1lbW9yeSBsZWFrcy5cbkV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzID0gMTA7XG5cbi8vIE9idmlvdXNseSBub3QgYWxsIEVtaXR0ZXJzIHNob3VsZCBiZSBsaW1pdGVkIHRvIDEwLiBUaGlzIGZ1bmN0aW9uIGFsbG93c1xuLy8gdGhhdCB0byBiZSBpbmNyZWFzZWQuIFNldCB0byB6ZXJvIGZvciB1bmxpbWl0ZWQuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnNldE1heExpc3RlbmVycyA9IGZ1bmN0aW9uKG4pIHtcbiAgaWYgKCFpc051bWJlcihuKSB8fCBuIDwgMCB8fCBpc05hTihuKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ24gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICB0aGlzLl9tYXhMaXN0ZW5lcnMgPSBuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgdmFyIGVyLCBoYW5kbGVyLCBsZW4sIGFyZ3MsIGksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBJZiB0aGVyZSBpcyBubyAnZXJyb3InIGV2ZW50IGxpc3RlbmVyIHRoZW4gdGhyb3cuXG4gIGlmICh0eXBlID09PSAnZXJyb3InKSB7XG4gICAgaWYgKCF0aGlzLl9ldmVudHMuZXJyb3IgfHxcbiAgICAgICAgKGlzT2JqZWN0KHRoaXMuX2V2ZW50cy5lcnJvcikgJiYgIXRoaXMuX2V2ZW50cy5lcnJvci5sZW5ndGgpKSB7XG4gICAgICBlciA9IGFyZ3VtZW50c1sxXTtcbiAgICAgIGlmIChlciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgICAgIHRocm93IGVyOyAvLyBVbmhhbmRsZWQgJ2Vycm9yJyBldmVudFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQXQgbGVhc3QgZ2l2ZSBzb21lIGtpbmQgb2YgY29udGV4dCB0byB0aGUgdXNlclxuICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCdVbmNhdWdodCwgdW5zcGVjaWZpZWQgXCJlcnJvclwiIGV2ZW50LiAoJyArIGVyICsgJyknKTtcbiAgICAgICAgZXJyLmNvbnRleHQgPSBlcjtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGhhbmRsZXIgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgaWYgKGlzVW5kZWZpbmVkKGhhbmRsZXIpKVxuICAgIHJldHVybiBmYWxzZTtcblxuICBpZiAoaXNGdW5jdGlvbihoYW5kbGVyKSkge1xuICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgLy8gZmFzdCBjYXNlc1xuICAgICAgY2FzZSAxOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyOlxuICAgICAgICBoYW5kbGVyLmNhbGwodGhpcywgYXJndW1lbnRzWzFdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0sIGFyZ3VtZW50c1syXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gc2xvd2VyXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgaGFuZGxlci5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoaXNPYmplY3QoaGFuZGxlcikpIHtcbiAgICBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICBsaXN0ZW5lcnMgPSBoYW5kbGVyLnNsaWNlKCk7XG4gICAgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspXG4gICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgYXJncyk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXIgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICB2YXIgbTtcblxuICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKVxuICAgIHRocm93IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgdGhpcy5fZXZlbnRzID0ge307XG5cbiAgLy8gVG8gYXZvaWQgcmVjdXJzaW9uIGluIHRoZSBjYXNlIHRoYXQgdHlwZSA9PT0gXCJuZXdMaXN0ZW5lclwiISBCZWZvcmVcbiAgLy8gYWRkaW5nIGl0IHRvIHRoZSBsaXN0ZW5lcnMsIGZpcnN0IGVtaXQgXCJuZXdMaXN0ZW5lclwiLlxuICBpZiAodGhpcy5fZXZlbnRzLm5ld0xpc3RlbmVyKVxuICAgIHRoaXMuZW1pdCgnbmV3TGlzdGVuZXInLCB0eXBlLFxuICAgICAgICAgICAgICBpc0Z1bmN0aW9uKGxpc3RlbmVyLmxpc3RlbmVyKSA/XG4gICAgICAgICAgICAgIGxpc3RlbmVyLmxpc3RlbmVyIDogbGlzdGVuZXIpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIC8vIE9wdGltaXplIHRoZSBjYXNlIG9mIG9uZSBsaXN0ZW5lci4gRG9uJ3QgbmVlZCB0aGUgZXh0cmEgYXJyYXkgb2JqZWN0LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IGxpc3RlbmVyO1xuICBlbHNlIGlmIChpc09iamVjdCh0aGlzLl9ldmVudHNbdHlwZV0pKVxuICAgIC8vIElmIHdlJ3ZlIGFscmVhZHkgZ290IGFuIGFycmF5LCBqdXN0IGFwcGVuZC5cbiAgICB0aGlzLl9ldmVudHNbdHlwZV0ucHVzaChsaXN0ZW5lcik7XG4gIGVsc2VcbiAgICAvLyBBZGRpbmcgdGhlIHNlY29uZCBlbGVtZW50LCBuZWVkIHRvIGNoYW5nZSB0byBhcnJheS5cbiAgICB0aGlzLl9ldmVudHNbdHlwZV0gPSBbdGhpcy5fZXZlbnRzW3R5cGVdLCBsaXN0ZW5lcl07XG5cbiAgLy8gQ2hlY2sgZm9yIGxpc3RlbmVyIGxlYWtcbiAgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkgJiYgIXRoaXMuX2V2ZW50c1t0eXBlXS53YXJuZWQpIHtcbiAgICBpZiAoIWlzVW5kZWZpbmVkKHRoaXMuX21heExpc3RlbmVycykpIHtcbiAgICAgIG0gPSB0aGlzLl9tYXhMaXN0ZW5lcnM7XG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSBFdmVudEVtaXR0ZXIuZGVmYXVsdE1heExpc3RlbmVycztcbiAgICB9XG5cbiAgICBpZiAobSAmJiBtID4gMCAmJiB0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoID4gbSkge1xuICAgICAgdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCA9IHRydWU7XG4gICAgICBjb25zb2xlLmVycm9yKCcobm9kZSkgd2FybmluZzogcG9zc2libGUgRXZlbnRFbWl0dGVyIG1lbW9yeSAnICtcbiAgICAgICAgICAgICAgICAgICAgJ2xlYWsgZGV0ZWN0ZWQuICVkIGxpc3RlbmVycyBhZGRlZC4gJyArXG4gICAgICAgICAgICAgICAgICAgICdVc2UgZW1pdHRlci5zZXRNYXhMaXN0ZW5lcnMoKSB0byBpbmNyZWFzZSBsaW1pdC4nLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ldmVudHNbdHlwZV0ubGVuZ3RoKTtcbiAgICAgIGlmICh0eXBlb2YgY29uc29sZS50cmFjZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAvLyBub3Qgc3VwcG9ydGVkIGluIElFIDEwXG4gICAgICAgIGNvbnNvbGUudHJhY2UoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub24gPSBFdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO1xuXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uY2UgPSBmdW5jdGlvbih0eXBlLCBsaXN0ZW5lcikge1xuICBpZiAoIWlzRnVuY3Rpb24obGlzdGVuZXIpKVxuICAgIHRocm93IFR5cGVFcnJvcignbGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG5cbiAgdmFyIGZpcmVkID0gZmFsc2U7XG5cbiAgZnVuY3Rpb24gZygpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGcpO1xuXG4gICAgaWYgKCFmaXJlZCkge1xuICAgICAgZmlyZWQgPSB0cnVlO1xuICAgICAgbGlzdGVuZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG4gIH1cblxuICBnLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gIHRoaXMub24odHlwZSwgZyk7XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBlbWl0cyBhICdyZW1vdmVMaXN0ZW5lcicgZXZlbnQgaWZmIHRoZSBsaXN0ZW5lciB3YXMgcmVtb3ZlZFxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBsaXN0LCBwb3NpdGlvbiwgbGVuZ3RoLCBpO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIHJldHVybiB0aGlzO1xuXG4gIGxpc3QgPSB0aGlzLl9ldmVudHNbdHlwZV07XG4gIGxlbmd0aCA9IGxpc3QubGVuZ3RoO1xuICBwb3NpdGlvbiA9IC0xO1xuXG4gIGlmIChsaXN0ID09PSBsaXN0ZW5lciB8fFxuICAgICAgKGlzRnVuY3Rpb24obGlzdC5saXN0ZW5lcikgJiYgbGlzdC5saXN0ZW5lciA9PT0gbGlzdGVuZXIpKSB7XG4gICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcblxuICB9IGVsc2UgaWYgKGlzT2JqZWN0KGxpc3QpKSB7XG4gICAgZm9yIChpID0gbGVuZ3RoOyBpLS0gPiAwOykge1xuICAgICAgaWYgKGxpc3RbaV0gPT09IGxpc3RlbmVyIHx8XG4gICAgICAgICAgKGxpc3RbaV0ubGlzdGVuZXIgJiYgbGlzdFtpXS5saXN0ZW5lciA9PT0gbGlzdGVuZXIpKSB7XG4gICAgICAgIHBvc2l0aW9uID0gaTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHBvc2l0aW9uIDwgMClcbiAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgICBsaXN0Lmxlbmd0aCA9IDA7XG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIH0gZWxzZSB7XG4gICAgICBsaXN0LnNwbGljZShwb3NpdGlvbiwgMSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcilcbiAgICAgIHRoaXMuZW1pdCgncmVtb3ZlTGlzdGVuZXInLCB0eXBlLCBsaXN0ZW5lcik7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIga2V5LCBsaXN0ZW5lcnM7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHMpXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgLy8gbm90IGxpc3RlbmluZyBmb3IgcmVtb3ZlTGlzdGVuZXIsIG5vIG5lZWQgdG8gZW1pdFxuICBpZiAoIXRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcikge1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKVxuICAgICAgdGhpcy5fZXZlbnRzID0ge307XG4gICAgZWxzZSBpZiAodGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgICAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8vIGVtaXQgcmVtb3ZlTGlzdGVuZXIgZm9yIGFsbCBsaXN0ZW5lcnMgb24gYWxsIGV2ZW50c1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIGZvciAoa2V5IGluIHRoaXMuX2V2ZW50cykge1xuICAgICAgaWYgKGtleSA9PT0gJ3JlbW92ZUxpc3RlbmVyJykgY29udGludWU7XG4gICAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycyhrZXkpO1xuICAgIH1cbiAgICB0aGlzLnJlbW92ZUFsbExpc3RlbmVycygncmVtb3ZlTGlzdGVuZXInKTtcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIGxpc3RlbmVycyA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNGdW5jdGlvbihsaXN0ZW5lcnMpKSB7XG4gICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnMpO1xuICB9IGVsc2UgaWYgKGxpc3RlbmVycykge1xuICAgIC8vIExJRk8gb3JkZXJcbiAgICB3aGlsZSAobGlzdGVuZXJzLmxlbmd0aClcbiAgICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgbGlzdGVuZXJzW2xpc3RlbmVycy5sZW5ndGggLSAxXSk7XG4gIH1cbiAgZGVsZXRlIHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgcmV0O1xuICBpZiAoIXRoaXMuX2V2ZW50cyB8fCAhdGhpcy5fZXZlbnRzW3R5cGVdKVxuICAgIHJldCA9IFtdO1xuICBlbHNlIGlmIChpc0Z1bmN0aW9uKHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgcmV0ID0gW3RoaXMuX2V2ZW50c1t0eXBlXV07XG4gIGVsc2VcbiAgICByZXQgPSB0aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtcbiAgcmV0dXJuIHJldDtcbn07XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgaWYgKHRoaXMuX2V2ZW50cykge1xuICAgIHZhciBldmxpc3RlbmVyID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gICAgaWYgKGlzRnVuY3Rpb24oZXZsaXN0ZW5lcikpXG4gICAgICByZXR1cm4gMTtcbiAgICBlbHNlIGlmIChldmxpc3RlbmVyKVxuICAgICAgcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RoO1xuICB9XG4gIHJldHVybiAwO1xufTtcblxuRXZlbnRFbWl0dGVyLmxpc3RlbmVyQ291bnQgPSBmdW5jdGlvbihlbWl0dGVyLCB0eXBlKSB7XG4gIHJldHVybiBlbWl0dGVyLmxpc3RlbmVyQ291bnQodHlwZSk7XG59O1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJztcbn1cblxuZnVuY3Rpb24gaXNOdW1iZXIoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG4iLCJ2YXIgaHR0cCA9IHJlcXVpcmUoJ2h0dHAnKTtcblxudmFyIGh0dHBzID0gbW9kdWxlLmV4cG9ydHM7XG5cbmZvciAodmFyIGtleSBpbiBodHRwKSB7XG4gICAgaWYgKGh0dHAuaGFzT3duUHJvcGVydHkoa2V5KSkgaHR0cHNba2V5XSA9IGh0dHBba2V5XTtcbn07XG5cbmh0dHBzLnJlcXVlc3QgPSBmdW5jdGlvbiAocGFyYW1zLCBjYikge1xuICAgIGlmICghcGFyYW1zKSBwYXJhbXMgPSB7fTtcbiAgICBwYXJhbXMuc2NoZW1lID0gJ2h0dHBzJztcbiAgICBwYXJhbXMucHJvdG9jb2wgPSAnaHR0cHM6JztcbiAgICByZXR1cm4gaHR0cC5yZXF1ZXN0LmNhbGwodGhpcywgcGFyYW1zLCBjYik7XG59XG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbVxuICB2YXIgZUxlbiA9IChuQnl0ZXMgKiA4KSAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgbkJpdHMgPSAtN1xuICB2YXIgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwXG4gIHZhciBkID0gaXNMRSA/IC0xIDogMVxuICB2YXIgcyA9IGJ1ZmZlcltvZmZzZXQgKyBpXVxuXG4gIGkgKz0gZFxuXG4gIGUgPSBzICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIHMgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IGVMZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgZSA9IChlICogMjU2KSArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IChtICogMjU2KSArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIGlmIChlID09PSAwKSB7XG4gICAgZSA9IDEgLSBlQmlhc1xuICB9IGVsc2UgaWYgKGUgPT09IGVNYXgpIHtcbiAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSlcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pXG4gICAgZSA9IGUgLSBlQmlhc1xuICB9XG4gIHJldHVybiAocyA/IC0xIDogMSkgKiBtICogTWF0aC5wb3coMiwgZSAtIG1MZW4pXG59XG5cbmV4cG9ydHMud3JpdGUgPSBmdW5jdGlvbiAoYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGNcbiAgdmFyIGVMZW4gPSAobkJ5dGVzICogOCkgLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKVxuICB2YXIgaSA9IGlzTEUgPyAwIDogKG5CeXRlcyAtIDEpXG4gIHZhciBkID0gaXNMRSA/IDEgOiAtMVxuICB2YXIgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMFxuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpXG5cbiAgaWYgKGlzTmFOKHZhbHVlKSB8fCB2YWx1ZSA9PT0gSW5maW5pdHkpIHtcbiAgICBtID0gaXNOYU4odmFsdWUpID8gMSA6IDBcbiAgICBlID0gZU1heFxuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKVxuICAgIGlmICh2YWx1ZSAqIChjID0gTWF0aC5wb3coMiwgLWUpKSA8IDEpIHtcbiAgICAgIGUtLVxuICAgICAgYyAqPSAyXG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlICs9IHJ0ICogTWF0aC5wb3coMiwgMSAtIGVCaWFzKVxuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrK1xuICAgICAgYyAvPSAyXG4gICAgfVxuXG4gICAgaWYgKGUgKyBlQmlhcyA+PSBlTWF4KSB7XG4gICAgICBtID0gMFxuICAgICAgZSA9IGVNYXhcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKCh2YWx1ZSAqIGMpIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IGUgKyBlQmlhc1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSAwXG4gICAgfVxuICB9XG5cbiAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCkge31cblxuICBlID0gKGUgPDwgbUxlbikgfCBtXG4gIGVMZW4gKz0gbUxlblxuICBmb3IgKDsgZUxlbiA+IDA7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IGUgJiAweGZmLCBpICs9IGQsIGUgLz0gMjU2LCBlTGVuIC09IDgpIHt9XG5cbiAgYnVmZmVyW29mZnNldCArIGkgLSBkXSB8PSBzICogMTI4XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8qIVxuICogRGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIEJ1ZmZlclxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxodHRwczovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cblxuLy8gVGhlIF9pc0J1ZmZlciBjaGVjayBpcyBmb3IgU2FmYXJpIDUtNyBzdXBwb3J0LCBiZWNhdXNlIGl0J3MgbWlzc2luZ1xuLy8gT2JqZWN0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHJldHVybiBvYmogIT0gbnVsbCAmJiAoaXNCdWZmZXIob2JqKSB8fCBpc1Nsb3dCdWZmZXIob2JqKSB8fCAhIW9iai5faXNCdWZmZXIpXG59XG5cbmZ1bmN0aW9uIGlzQnVmZmVyIChvYmopIHtcbiAgcmV0dXJuICEhb2JqLmNvbnN0cnVjdG9yICYmIHR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIgPT09ICdmdW5jdGlvbicgJiYgb2JqLmNvbnN0cnVjdG9yLmlzQnVmZmVyKG9iailcbn1cblxuLy8gRm9yIE5vZGUgdjAuMTAgc3VwcG9ydC4gUmVtb3ZlIHRoaXMgZXZlbnR1YWxseS5cbmZ1bmN0aW9uIGlzU2xvd0J1ZmZlciAob2JqKSB7XG4gIHJldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFID09PSAnZnVuY3Rpb24nICYmIHR5cGVvZiBvYmouc2xpY2UgPT09ICdmdW5jdGlvbicgJiYgaXNCdWZmZXIob2JqLnNsaWNlKDAsIDApKVxufVxuIiwidmFyIHRvU3RyaW5nID0ge30udG9TdHJpbmc7XG5cbm1vZHVsZS5leHBvcnRzID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiAoYXJyKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKGFycikgPT0gJ1tvYmplY3QgQXJyYXldJztcbn07XG4iLCIhZnVuY3Rpb24oZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgJ29iamVjdCcgPT0gdHlwZW9mIGV4cG9ydHMgJiYgJ3VuZGVmaW5lZCcgIT0gdHlwZW9mIG1vZHVsZSA/IGZhY3RvcnkoZXhwb3J0cykgOiAnZnVuY3Rpb24nID09IHR5cGVvZiBkZWZpbmUgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbICdleHBvcnRzJyBdLCBmYWN0b3J5KSA6IGZhY3RvcnkoZ2xvYmFsLnByZWFjdCA9IGdsb2JhbC5wcmVhY3QgfHwge30pO1xufSh0aGlzLCBmdW5jdGlvbihleHBvcnRzKSB7XG4gICAgZnVuY3Rpb24gVk5vZGUobm9kZU5hbWUsIGF0dHJpYnV0ZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgIHRoaXMubm9kZU5hbWUgPSBub2RlTmFtZTtcbiAgICAgICAgdGhpcy5hdHRyaWJ1dGVzID0gYXR0cmlidXRlcztcbiAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuO1xuICAgICAgICB0aGlzLmtleSA9IGF0dHJpYnV0ZXMgJiYgYXR0cmlidXRlcy5rZXk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGgobm9kZU5hbWUsIGF0dHJpYnV0ZXMpIHtcbiAgICAgICAgdmFyIGxhc3RTaW1wbGUsIGNoaWxkLCBzaW1wbGUsIGksIGNoaWxkcmVuID0gW107XG4gICAgICAgIGZvciAoaSA9IGFyZ3VtZW50cy5sZW5ndGg7IGktLSA+IDI7ICkgc3RhY2sucHVzaChhcmd1bWVudHNbaV0pO1xuICAgICAgICBpZiAoYXR0cmlidXRlcyAmJiBhdHRyaWJ1dGVzLmNoaWxkcmVuKSB7XG4gICAgICAgICAgICBpZiAoIXN0YWNrLmxlbmd0aCkgc3RhY2sucHVzaChhdHRyaWJ1dGVzLmNoaWxkcmVuKTtcbiAgICAgICAgICAgIGRlbGV0ZSBhdHRyaWJ1dGVzLmNoaWxkcmVuO1xuICAgICAgICB9XG4gICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGgpIGlmICgoY2hpbGQgPSBzdGFjay5wb3AoKSkgaW5zdGFuY2VvZiBBcnJheSkgZm9yIChpID0gY2hpbGQubGVuZ3RoOyBpLS07ICkgc3RhY2sucHVzaChjaGlsZFtpXSk7IGVsc2UgaWYgKG51bGwgIT0gY2hpbGQgJiYgY2hpbGQgIT09ICExKSB7XG4gICAgICAgICAgICBpZiAoJ251bWJlcicgPT0gdHlwZW9mIGNoaWxkIHx8IGNoaWxkID09PSAhMCkgY2hpbGQgPSBTdHJpbmcoY2hpbGQpO1xuICAgICAgICAgICAgc2ltcGxlID0gJ3N0cmluZycgPT0gdHlwZW9mIGNoaWxkO1xuICAgICAgICAgICAgaWYgKHNpbXBsZSAmJiBsYXN0U2ltcGxlKSBjaGlsZHJlbltjaGlsZHJlbi5sZW5ndGggLSAxXSArPSBjaGlsZDsgZWxzZSB7XG4gICAgICAgICAgICAgICAgY2hpbGRyZW4ucHVzaChjaGlsZCk7XG4gICAgICAgICAgICAgICAgbGFzdFNpbXBsZSA9IHNpbXBsZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgcCA9IG5ldyBWTm9kZShub2RlTmFtZSwgYXR0cmlidXRlcyB8fCB2b2lkIDAsIGNoaWxkcmVuKTtcbiAgICAgICAgaWYgKG9wdGlvbnMudm5vZGUpIG9wdGlvbnMudm5vZGUocCk7XG4gICAgICAgIHJldHVybiBwO1xuICAgIH1cbiAgICBmdW5jdGlvbiBleHRlbmQob2JqLCBwcm9wcykge1xuICAgICAgICBpZiAocHJvcHMpIGZvciAodmFyIGkgaW4gcHJvcHMpIG9ialtpXSA9IHByb3BzW2ldO1xuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjbG9uZShvYmopIHtcbiAgICAgICAgcmV0dXJuIGV4dGVuZCh7fSwgb2JqKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZGVsdmUob2JqLCBrZXkpIHtcbiAgICAgICAgZm9yICh2YXIgcCA9IGtleS5zcGxpdCgnLicpLCBpID0gMDsgaSA8IHAubGVuZ3RoICYmIG9iajsgaSsrKSBvYmogPSBvYmpbcFtpXV07XG4gICAgICAgIHJldHVybiBvYmo7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGlzRnVuY3Rpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiAnZnVuY3Rpb24nID09IHR5cGVvZiBvYmo7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGlzU3RyaW5nKG9iaikge1xuICAgICAgICByZXR1cm4gJ3N0cmluZycgPT0gdHlwZW9mIG9iajtcbiAgICB9XG4gICAgZnVuY3Rpb24gaGFzaFRvQ2xhc3NOYW1lKGMpIHtcbiAgICAgICAgdmFyIHN0ciA9ICcnO1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIGMpIGlmIChjW3Byb3BdKSB7XG4gICAgICAgICAgICBpZiAoc3RyKSBzdHIgKz0gJyAnO1xuICAgICAgICAgICAgc3RyICs9IHByb3A7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0cjtcbiAgICB9XG4gICAgZnVuY3Rpb24gY2xvbmVFbGVtZW50KHZub2RlLCBwcm9wcykge1xuICAgICAgICByZXR1cm4gaCh2bm9kZS5ub2RlTmFtZSwgZXh0ZW5kKGNsb25lKHZub2RlLmF0dHJpYnV0ZXMpLCBwcm9wcyksIGFyZ3VtZW50cy5sZW5ndGggPiAyID8gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpIDogdm5vZGUuY2hpbGRyZW4pO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjcmVhdGVMaW5rZWRTdGF0ZShjb21wb25lbnQsIGtleSwgZXZlbnRQYXRoKSB7XG4gICAgICAgIHZhciBwYXRoID0ga2V5LnNwbGl0KCcuJyk7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbihlKSB7XG4gICAgICAgICAgICB2YXIgdCA9IGUgJiYgZS50YXJnZXQgfHwgdGhpcywgc3RhdGUgPSB7fSwgb2JqID0gc3RhdGUsIHYgPSBpc1N0cmluZyhldmVudFBhdGgpID8gZGVsdmUoZSwgZXZlbnRQYXRoKSA6IHQubm9kZU5hbWUgPyB0LnR5cGUubWF0Y2goL15jaGV8cmFkLykgPyB0LmNoZWNrZWQgOiB0LnZhbHVlIDogZSwgaSA9IDA7XG4gICAgICAgICAgICBmb3IgKDtpIDwgcGF0aC5sZW5ndGggLSAxOyBpKyspIG9iaiA9IG9ialtwYXRoW2ldXSB8fCAob2JqW3BhdGhbaV1dID0gIWkgJiYgY29tcG9uZW50LnN0YXRlW3BhdGhbaV1dIHx8IHt9KTtcbiAgICAgICAgICAgIG9ialtwYXRoW2ldXSA9IHY7XG4gICAgICAgICAgICBjb21wb25lbnQuc2V0U3RhdGUoc3RhdGUpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBlbnF1ZXVlUmVuZGVyKGNvbXBvbmVudCkge1xuICAgICAgICBpZiAoIWNvbXBvbmVudC5fZGlydHkgJiYgKGNvbXBvbmVudC5fZGlydHkgPSAhMCkgJiYgMSA9PSBpdGVtcy5wdXNoKGNvbXBvbmVudCkpIChvcHRpb25zLmRlYm91bmNlUmVuZGVyaW5nIHx8IGRlZmVyKShyZXJlbmRlcik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlcmVuZGVyKCkge1xuICAgICAgICB2YXIgcCwgbGlzdCA9IGl0ZW1zO1xuICAgICAgICBpdGVtcyA9IFtdO1xuICAgICAgICB3aGlsZSAocCA9IGxpc3QucG9wKCkpIGlmIChwLl9kaXJ0eSkgcmVuZGVyQ29tcG9uZW50KHApO1xuICAgIH1cbiAgICBmdW5jdGlvbiBpc0Z1bmN0aW9uYWxDb21wb25lbnQodm5vZGUpIHtcbiAgICAgICAgdmFyIG5vZGVOYW1lID0gdm5vZGUgJiYgdm5vZGUubm9kZU5hbWU7XG4gICAgICAgIHJldHVybiBub2RlTmFtZSAmJiBpc0Z1bmN0aW9uKG5vZGVOYW1lKSAmJiAhKG5vZGVOYW1lLnByb3RvdHlwZSAmJiBub2RlTmFtZS5wcm90b3R5cGUucmVuZGVyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYnVpbGRGdW5jdGlvbmFsQ29tcG9uZW50KHZub2RlLCBjb250ZXh0KSB7XG4gICAgICAgIHJldHVybiB2bm9kZS5ub2RlTmFtZShnZXROb2RlUHJvcHModm5vZGUpLCBjb250ZXh0IHx8IEVNUFRZKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gaXNTYW1lTm9kZVR5cGUobm9kZSwgdm5vZGUpIHtcbiAgICAgICAgaWYgKGlzU3RyaW5nKHZub2RlKSkgcmV0dXJuIG5vZGUgaW5zdGFuY2VvZiBUZXh0O1xuICAgICAgICBpZiAoaXNTdHJpbmcodm5vZGUubm9kZU5hbWUpKSByZXR1cm4gaXNOYW1lZE5vZGUobm9kZSwgdm5vZGUubm9kZU5hbWUpO1xuICAgICAgICBpZiAoaXNGdW5jdGlvbih2bm9kZS5ub2RlTmFtZSkpIHJldHVybiBub2RlLl9jb21wb25lbnRDb25zdHJ1Y3RvciA9PT0gdm5vZGUubm9kZU5hbWUgfHwgaXNGdW5jdGlvbmFsQ29tcG9uZW50KHZub2RlKTsgZWxzZSA7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGlzTmFtZWROb2RlKG5vZGUsIG5vZGVOYW1lKSB7XG4gICAgICAgIHJldHVybiBub2RlLm5vcm1hbGl6ZWROb2RlTmFtZSA9PT0gbm9kZU5hbWUgfHwgdG9Mb3dlckNhc2Uobm9kZS5ub2RlTmFtZSkgPT09IHRvTG93ZXJDYXNlKG5vZGVOYW1lKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZ2V0Tm9kZVByb3BzKHZub2RlKSB7XG4gICAgICAgIHZhciBwcm9wcyA9IGNsb25lKHZub2RlLmF0dHJpYnV0ZXMpO1xuICAgICAgICBwcm9wcy5jaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuICAgICAgICB2YXIgZGVmYXVsdFByb3BzID0gdm5vZGUubm9kZU5hbWUuZGVmYXVsdFByb3BzO1xuICAgICAgICBpZiAoZGVmYXVsdFByb3BzKSBmb3IgKHZhciBpIGluIGRlZmF1bHRQcm9wcykgaWYgKHZvaWQgMCA9PT0gcHJvcHNbaV0pIHByb3BzW2ldID0gZGVmYXVsdFByb3BzW2ldO1xuICAgICAgICByZXR1cm4gcHJvcHM7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUobm9kZSkge1xuICAgICAgICB2YXIgcCA9IG5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgaWYgKHApIHAucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNldEFjY2Vzc29yKG5vZGUsIG5hbWUsIG9sZCwgdmFsdWUsIGlzU3ZnKSB7XG4gICAgICAgIGlmICgnY2xhc3NOYW1lJyA9PT0gbmFtZSkgbmFtZSA9ICdjbGFzcyc7XG4gICAgICAgIGlmICgnY2xhc3MnID09PSBuYW1lICYmIHZhbHVlICYmICdvYmplY3QnID09IHR5cGVvZiB2YWx1ZSkgdmFsdWUgPSBoYXNoVG9DbGFzc05hbWUodmFsdWUpO1xuICAgICAgICBpZiAoJ2tleScgPT09IG5hbWUpIDsgZWxzZSBpZiAoJ2NsYXNzJyA9PT0gbmFtZSAmJiAhaXNTdmcpIG5vZGUuY2xhc3NOYW1lID0gdmFsdWUgfHwgJyc7IGVsc2UgaWYgKCdzdHlsZScgPT09IG5hbWUpIHtcbiAgICAgICAgICAgIGlmICghdmFsdWUgfHwgaXNTdHJpbmcodmFsdWUpIHx8IGlzU3RyaW5nKG9sZCkpIG5vZGUuc3R5bGUuY3NzVGV4dCA9IHZhbHVlIHx8ICcnO1xuICAgICAgICAgICAgaWYgKHZhbHVlICYmICdvYmplY3QnID09IHR5cGVvZiB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghaXNTdHJpbmcob2xkKSkgZm9yICh2YXIgaSBpbiBvbGQpIGlmICghKGkgaW4gdmFsdWUpKSBub2RlLnN0eWxlW2ldID0gJyc7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiB2YWx1ZSkgbm9kZS5zdHlsZVtpXSA9ICdudW1iZXInID09IHR5cGVvZiB2YWx1ZVtpXSAmJiAhTk9OX0RJTUVOU0lPTl9QUk9QU1tpXSA/IHZhbHVlW2ldICsgJ3B4JyA6IHZhbHVlW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCdkYW5nZXJvdXNseVNldElubmVySFRNTCcgPT09IG5hbWUpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSkgbm9kZS5pbm5lckhUTUwgPSB2YWx1ZS5fX2h0bWw7XG4gICAgICAgIH0gZWxzZSBpZiAoJ28nID09IG5hbWVbMF0gJiYgJ24nID09IG5hbWVbMV0pIHtcbiAgICAgICAgICAgIHZhciBsID0gbm9kZS5fbGlzdGVuZXJzIHx8IChub2RlLl9saXN0ZW5lcnMgPSB7fSk7XG4gICAgICAgICAgICBuYW1lID0gdG9Mb3dlckNhc2UobmFtZS5zdWJzdHJpbmcoMikpO1xuICAgICAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFsW25hbWVdKSBub2RlLmFkZEV2ZW50TGlzdGVuZXIobmFtZSwgZXZlbnRQcm94eSwgISFOT05fQlVCQkxJTkdfRVZFTlRTW25hbWVdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobFtuYW1lXSkgbm9kZS5yZW1vdmVFdmVudExpc3RlbmVyKG5hbWUsIGV2ZW50UHJveHksICEhTk9OX0JVQkJMSU5HX0VWRU5UU1tuYW1lXSk7XG4gICAgICAgICAgICBsW25hbWVdID0gdmFsdWU7XG4gICAgICAgIH0gZWxzZSBpZiAoJ2xpc3QnICE9PSBuYW1lICYmICd0eXBlJyAhPT0gbmFtZSAmJiAhaXNTdmcgJiYgbmFtZSBpbiBub2RlKSB7XG4gICAgICAgICAgICBzZXRQcm9wZXJ0eShub2RlLCBuYW1lLCBudWxsID09IHZhbHVlID8gJycgOiB2YWx1ZSk7XG4gICAgICAgICAgICBpZiAobnVsbCA9PSB2YWx1ZSB8fCB2YWx1ZSA9PT0gITEpIG5vZGUucmVtb3ZlQXR0cmlidXRlKG5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIG5zID0gaXNTdmcgJiYgbmFtZS5tYXRjaCgvXnhsaW5rXFw6PyguKykvKTtcbiAgICAgICAgICAgIGlmIChudWxsID09IHZhbHVlIHx8IHZhbHVlID09PSAhMSkgaWYgKG5zKSBub2RlLnJlbW92ZUF0dHJpYnV0ZU5TKCdodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rJywgdG9Mb3dlckNhc2UobnNbMV0pKTsgZWxzZSBub2RlLnJlbW92ZUF0dHJpYnV0ZShuYW1lKTsgZWxzZSBpZiAoJ29iamVjdCcgIT0gdHlwZW9mIHZhbHVlICYmICFpc0Z1bmN0aW9uKHZhbHVlKSkgaWYgKG5zKSBub2RlLnNldEF0dHJpYnV0ZU5TKCdodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rJywgdG9Mb3dlckNhc2UobnNbMV0pLCB2YWx1ZSk7IGVsc2Ugbm9kZS5zZXRBdHRyaWJ1dGUobmFtZSwgdmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNldFByb3BlcnR5KG5vZGUsIG5hbWUsIHZhbHVlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBub2RlW25hbWVdID0gdmFsdWU7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGV2ZW50UHJveHkoZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGlzdGVuZXJzW2UudHlwZV0ob3B0aW9ucy5ldmVudCAmJiBvcHRpb25zLmV2ZW50KGUpIHx8IGUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjb2xsZWN0Tm9kZShub2RlKSB7XG4gICAgICAgIHJlbW92ZU5vZGUobm9kZSk7XG4gICAgICAgIGlmIChub2RlIGluc3RhbmNlb2YgRWxlbWVudCkge1xuICAgICAgICAgICAgbm9kZS5fY29tcG9uZW50ID0gbm9kZS5fY29tcG9uZW50Q29uc3RydWN0b3IgPSBudWxsO1xuICAgICAgICAgICAgdmFyIF9uYW1lID0gbm9kZS5ub3JtYWxpemVkTm9kZU5hbWUgfHwgdG9Mb3dlckNhc2Uobm9kZS5ub2RlTmFtZSk7XG4gICAgICAgICAgICAobm9kZXNbX25hbWVdIHx8IChub2Rlc1tfbmFtZV0gPSBbXSkpLnB1c2gobm9kZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gY3JlYXRlTm9kZShub2RlTmFtZSwgaXNTdmcpIHtcbiAgICAgICAgdmFyIG5hbWUgPSB0b0xvd2VyQ2FzZShub2RlTmFtZSksIG5vZGUgPSBub2Rlc1tuYW1lXSAmJiBub2Rlc1tuYW1lXS5wb3AoKSB8fCAoaXNTdmcgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50TlMoJ2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJywgbm9kZU5hbWUpIDogZG9jdW1lbnQuY3JlYXRlRWxlbWVudChub2RlTmFtZSkpO1xuICAgICAgICBub2RlLm5vcm1hbGl6ZWROb2RlTmFtZSA9IG5hbWU7XG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH1cbiAgICBmdW5jdGlvbiBmbHVzaE1vdW50cygpIHtcbiAgICAgICAgdmFyIGM7XG4gICAgICAgIHdoaWxlIChjID0gbW91bnRzLnBvcCgpKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5hZnRlck1vdW50KSBvcHRpb25zLmFmdGVyTW91bnQoYyk7XG4gICAgICAgICAgICBpZiAoYy5jb21wb25lbnREaWRNb3VudCkgYy5jb21wb25lbnREaWRNb3VudCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRpZmYoZG9tLCB2bm9kZSwgY29udGV4dCwgbW91bnRBbGwsIHBhcmVudCwgY29tcG9uZW50Um9vdCkge1xuICAgICAgICBpZiAoIWRpZmZMZXZlbCsrKSBpc1N2Z01vZGUgPSBwYXJlbnQgaW5zdGFuY2VvZiBTVkdFbGVtZW50O1xuICAgICAgICB2YXIgcmV0ID0gaWRpZmYoZG9tLCB2bm9kZSwgY29udGV4dCwgbW91bnRBbGwpO1xuICAgICAgICBpZiAocGFyZW50ICYmIHJldC5wYXJlbnROb2RlICE9PSBwYXJlbnQpIHBhcmVudC5hcHBlbmRDaGlsZChyZXQpO1xuICAgICAgICBpZiAoIS0tZGlmZkxldmVsICYmICFjb21wb25lbnRSb290KSBmbHVzaE1vdW50cygpO1xuICAgICAgICByZXR1cm4gcmV0O1xuICAgIH1cbiAgICBmdW5jdGlvbiBpZGlmZihkb20sIHZub2RlLCBjb250ZXh0LCBtb3VudEFsbCkge1xuICAgICAgICB2YXIgb3JpZ2luYWxBdHRyaWJ1dGVzID0gdm5vZGUgJiYgdm5vZGUuYXR0cmlidXRlcztcbiAgICAgICAgd2hpbGUgKGlzRnVuY3Rpb25hbENvbXBvbmVudCh2bm9kZSkpIHZub2RlID0gYnVpbGRGdW5jdGlvbmFsQ29tcG9uZW50KHZub2RlLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKG51bGwgPT0gdm5vZGUpIHZub2RlID0gJyc7XG4gICAgICAgIGlmIChpc1N0cmluZyh2bm9kZSkpIHtcbiAgICAgICAgICAgIGlmIChkb20pIHtcbiAgICAgICAgICAgICAgICBpZiAoZG9tIGluc3RhbmNlb2YgVGV4dCAmJiBkb20ucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tLm5vZGVWYWx1ZSAhPSB2bm9kZSkgZG9tLm5vZGVWYWx1ZSA9IHZub2RlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZWNvbGxlY3ROb2RlVHJlZShkb20pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGRvY3VtZW50LmNyZWF0ZVRleHROb2RlKHZub2RlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNGdW5jdGlvbih2bm9kZS5ub2RlTmFtZSkpIHJldHVybiBidWlsZENvbXBvbmVudEZyb21WTm9kZShkb20sIHZub2RlLCBjb250ZXh0LCBtb3VudEFsbCk7XG4gICAgICAgIHZhciBvdXQgPSBkb20sIG5vZGVOYW1lID0gdm5vZGUubm9kZU5hbWUsIHByZXZTdmdNb2RlID0gaXNTdmdNb2RlLCB2Y2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcbiAgICAgICAgaWYgKCFpc1N0cmluZyhub2RlTmFtZSkpIG5vZGVOYW1lID0gU3RyaW5nKG5vZGVOYW1lKTtcbiAgICAgICAgaXNTdmdNb2RlID0gJ3N2ZycgPT09IG5vZGVOYW1lID8gITAgOiAnZm9yZWlnbk9iamVjdCcgPT09IG5vZGVOYW1lID8gITEgOiBpc1N2Z01vZGU7XG4gICAgICAgIGlmICghZG9tKSBvdXQgPSBjcmVhdGVOb2RlKG5vZGVOYW1lLCBpc1N2Z01vZGUpOyBlbHNlIGlmICghaXNOYW1lZE5vZGUoZG9tLCBub2RlTmFtZSkpIHtcbiAgICAgICAgICAgIG91dCA9IGNyZWF0ZU5vZGUobm9kZU5hbWUsIGlzU3ZnTW9kZSk7XG4gICAgICAgICAgICB3aGlsZSAoZG9tLmZpcnN0Q2hpbGQpIG91dC5hcHBlbmRDaGlsZChkb20uZmlyc3RDaGlsZCk7XG4gICAgICAgICAgICByZWNvbGxlY3ROb2RlVHJlZShkb20pO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2Y2hpbGRyZW4gJiYgMSA9PT0gdmNoaWxkcmVuLmxlbmd0aCAmJiAnc3RyaW5nJyA9PSB0eXBlb2YgdmNoaWxkcmVuWzBdICYmIDEgPT09IG91dC5jaGlsZE5vZGVzLmxlbmd0aCAmJiBvdXQuZmlyc3RDaGlsZCBpbnN0YW5jZW9mIFRleHQpIHtcbiAgICAgICAgICAgIGlmIChvdXQuZmlyc3RDaGlsZC5ub2RlVmFsdWUgIT0gdmNoaWxkcmVuWzBdKSBvdXQuZmlyc3RDaGlsZC5ub2RlVmFsdWUgPSB2Y2hpbGRyZW5bMF07XG4gICAgICAgIH0gZWxzZSBpZiAodmNoaWxkcmVuICYmIHZjaGlsZHJlbi5sZW5ndGggfHwgb3V0LmZpcnN0Q2hpbGQpIGlubmVyRGlmZk5vZGUob3V0LCB2Y2hpbGRyZW4sIGNvbnRleHQsIG1vdW50QWxsKTtcbiAgICAgICAgdmFyIHByb3BzID0gb3V0W0FUVFJfS0VZXTtcbiAgICAgICAgaWYgKCFwcm9wcykge1xuICAgICAgICAgICAgb3V0W0FUVFJfS0VZXSA9IHByb3BzID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBhID0gb3V0LmF0dHJpYnV0ZXMsIGkgPSBhLmxlbmd0aDsgaS0tOyApIHByb3BzW2FbaV0ubmFtZV0gPSBhW2ldLnZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGRpZmZBdHRyaWJ1dGVzKG91dCwgdm5vZGUuYXR0cmlidXRlcywgcHJvcHMpO1xuICAgICAgICBpZiAob3JpZ2luYWxBdHRyaWJ1dGVzICYmICdmdW5jdGlvbicgPT0gdHlwZW9mIG9yaWdpbmFsQXR0cmlidXRlcy5yZWYpIChwcm9wcy5yZWYgPSBvcmlnaW5hbEF0dHJpYnV0ZXMucmVmKShvdXQpO1xuICAgICAgICBpc1N2Z01vZGUgPSBwcmV2U3ZnTW9kZTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG4gICAgZnVuY3Rpb24gaW5uZXJEaWZmTm9kZShkb20sIHZjaGlsZHJlbiwgY29udGV4dCwgbW91bnRBbGwpIHtcbiAgICAgICAgdmFyIGosIGMsIHZjaGlsZCwgY2hpbGQsIG9yaWdpbmFsQ2hpbGRyZW4gPSBkb20uY2hpbGROb2RlcywgY2hpbGRyZW4gPSBbXSwga2V5ZWQgPSB7fSwga2V5ZWRMZW4gPSAwLCBtaW4gPSAwLCBsZW4gPSBvcmlnaW5hbENoaWxkcmVuLmxlbmd0aCwgY2hpbGRyZW5MZW4gPSAwLCB2bGVuID0gdmNoaWxkcmVuICYmIHZjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgIGlmIChsZW4pIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgIHZhciBfY2hpbGQgPSBvcmlnaW5hbENoaWxkcmVuW2ldLCBrZXkgPSB2bGVuID8gKGMgPSBfY2hpbGQuX2NvbXBvbmVudCkgPyBjLl9fa2V5IDogKGMgPSBfY2hpbGRbQVRUUl9LRVldKSA/IGMua2V5IDogbnVsbCA6IG51bGw7XG4gICAgICAgICAgICBpZiAoa2V5IHx8IDAgPT09IGtleSkge1xuICAgICAgICAgICAgICAgIGtleWVkTGVuKys7XG4gICAgICAgICAgICAgICAga2V5ZWRba2V5XSA9IF9jaGlsZDtcbiAgICAgICAgICAgIH0gZWxzZSBjaGlsZHJlbltjaGlsZHJlbkxlbisrXSA9IF9jaGlsZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmxlbikgZm9yICh2YXIgaSA9IDA7IGkgPCB2bGVuOyBpKyspIHtcbiAgICAgICAgICAgIHZjaGlsZCA9IHZjaGlsZHJlbltpXTtcbiAgICAgICAgICAgIGNoaWxkID0gbnVsbDtcbiAgICAgICAgICAgIHZhciBrZXkgPSB2Y2hpbGQua2V5O1xuICAgICAgICAgICAgaWYgKG51bGwgIT0ga2V5KSB7XG4gICAgICAgICAgICAgICAgaWYgKGtleWVkTGVuICYmIGtleSBpbiBrZXllZCkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZCA9IGtleWVkW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGtleWVkW2tleV0gPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgICAgIGtleWVkTGVuLS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICghY2hpbGQgJiYgbWluIDwgY2hpbGRyZW5MZW4pIHtcbiAgICAgICAgICAgICAgICBmb3IgKGogPSBtaW47IGogPCBjaGlsZHJlbkxlbjsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGMgPSBjaGlsZHJlbltqXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGMgJiYgaXNTYW1lTm9kZVR5cGUoYywgdmNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGQgPSBjO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW5bal0gPSB2b2lkIDA7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaiA9PT0gY2hpbGRyZW5MZW4gLSAxKSBjaGlsZHJlbkxlbi0tO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGogPT09IG1pbikgbWluKys7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkICYmIG1pbiA8IGNoaWxkcmVuTGVuICYmIGlzRnVuY3Rpb24odmNoaWxkLm5vZGVOYW1lKSAmJiBtb3VudEFsbCkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZCA9IGNoaWxkcmVuW21pbl07XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuW21pbisrXSA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjaGlsZCA9IGlkaWZmKGNoaWxkLCB2Y2hpbGQsIGNvbnRleHQsIG1vdW50QWxsKTtcbiAgICAgICAgICAgIGlmIChjaGlsZCAmJiBjaGlsZCAhPT0gZG9tICYmIGNoaWxkICE9PSBvcmlnaW5hbENoaWxkcmVuW2ldKSBkb20uaW5zZXJ0QmVmb3JlKGNoaWxkLCBvcmlnaW5hbENoaWxkcmVuW2ldIHx8IG51bGwpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXllZExlbikgZm9yICh2YXIgaSBpbiBrZXllZCkgaWYgKGtleWVkW2ldKSByZWNvbGxlY3ROb2RlVHJlZShrZXllZFtpXSk7XG4gICAgICAgIGlmIChtaW4gPCBjaGlsZHJlbkxlbikgcmVtb3ZlT3JwaGFuZWRDaGlsZHJlbihjaGlsZHJlbik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlbW92ZU9ycGhhbmVkQ2hpbGRyZW4oY2hpbGRyZW4sIHVubW91bnRPbmx5KSB7XG4gICAgICAgIGZvciAodmFyIGkgPSBjaGlsZHJlbi5sZW5ndGg7IGktLTsgKSBpZiAoY2hpbGRyZW5baV0pIHJlY29sbGVjdE5vZGVUcmVlKGNoaWxkcmVuW2ldLCB1bm1vdW50T25seSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlY29sbGVjdE5vZGVUcmVlKG5vZGUsIHVubW91bnRPbmx5KSB7XG4gICAgICAgIHZhciBjb21wb25lbnQgPSBub2RlLl9jb21wb25lbnQ7XG4gICAgICAgIGlmIChjb21wb25lbnQpIHVubW91bnRDb21wb25lbnQoY29tcG9uZW50LCAhdW5tb3VudE9ubHkpOyBlbHNlIHtcbiAgICAgICAgICAgIGlmIChub2RlW0FUVFJfS0VZXSAmJiBub2RlW0FUVFJfS0VZXS5yZWYpIG5vZGVbQVRUUl9LRVldLnJlZihudWxsKTtcbiAgICAgICAgICAgIGlmICghdW5tb3VudE9ubHkpIGNvbGxlY3ROb2RlKG5vZGUpO1xuICAgICAgICAgICAgaWYgKG5vZGUuY2hpbGROb2RlcyAmJiBub2RlLmNoaWxkTm9kZXMubGVuZ3RoKSByZW1vdmVPcnBoYW5lZENoaWxkcmVuKG5vZGUuY2hpbGROb2RlcywgdW5tb3VudE9ubHkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRpZmZBdHRyaWJ1dGVzKGRvbSwgYXR0cnMsIG9sZCkge1xuICAgICAgICBmb3IgKHZhciBfbmFtZSBpbiBvbGQpIGlmICghKGF0dHJzICYmIF9uYW1lIGluIGF0dHJzKSAmJiBudWxsICE9IG9sZFtfbmFtZV0pIHNldEFjY2Vzc29yKGRvbSwgX25hbWUsIG9sZFtfbmFtZV0sIG9sZFtfbmFtZV0gPSB2b2lkIDAsIGlzU3ZnTW9kZSk7XG4gICAgICAgIGlmIChhdHRycykgZm9yICh2YXIgX25hbWUyIGluIGF0dHJzKSBpZiAoISgnY2hpbGRyZW4nID09PSBfbmFtZTIgfHwgJ2lubmVySFRNTCcgPT09IF9uYW1lMiB8fCBfbmFtZTIgaW4gb2xkICYmIGF0dHJzW19uYW1lMl0gPT09ICgndmFsdWUnID09PSBfbmFtZTIgfHwgJ2NoZWNrZWQnID09PSBfbmFtZTIgPyBkb21bX25hbWUyXSA6IG9sZFtfbmFtZTJdKSkpIHNldEFjY2Vzc29yKGRvbSwgX25hbWUyLCBvbGRbX25hbWUyXSwgb2xkW19uYW1lMl0gPSBhdHRyc1tfbmFtZTJdLCBpc1N2Z01vZGUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjb2xsZWN0Q29tcG9uZW50KGNvbXBvbmVudCkge1xuICAgICAgICB2YXIgbmFtZSA9IGNvbXBvbmVudC5jb25zdHJ1Y3Rvci5uYW1lLCBsaXN0ID0gY29tcG9uZW50c1tuYW1lXTtcbiAgICAgICAgaWYgKGxpc3QpIGxpc3QucHVzaChjb21wb25lbnQpOyBlbHNlIGNvbXBvbmVudHNbbmFtZV0gPSBbIGNvbXBvbmVudCBdO1xuICAgIH1cbiAgICBmdW5jdGlvbiBjcmVhdGVDb21wb25lbnQoQ3RvciwgcHJvcHMsIGNvbnRleHQpIHtcbiAgICAgICAgdmFyIGluc3QgPSBuZXcgQ3Rvcihwcm9wcywgY29udGV4dCksIGxpc3QgPSBjb21wb25lbnRzW0N0b3IubmFtZV07XG4gICAgICAgIENvbXBvbmVudC5jYWxsKGluc3QsIHByb3BzLCBjb250ZXh0KTtcbiAgICAgICAgaWYgKGxpc3QpIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aDsgaS0tOyApIGlmIChsaXN0W2ldLmNvbnN0cnVjdG9yID09PSBDdG9yKSB7XG4gICAgICAgICAgICBpbnN0Lm5leHRCYXNlID0gbGlzdFtpXS5uZXh0QmFzZTtcbiAgICAgICAgICAgIGxpc3Quc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGluc3Q7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNldENvbXBvbmVudFByb3BzKGNvbXBvbmVudCwgcHJvcHMsIG9wdHMsIGNvbnRleHQsIG1vdW50QWxsKSB7XG4gICAgICAgIGlmICghY29tcG9uZW50Ll9kaXNhYmxlKSB7XG4gICAgICAgICAgICBjb21wb25lbnQuX2Rpc2FibGUgPSAhMDtcbiAgICAgICAgICAgIGlmIChjb21wb25lbnQuX19yZWYgPSBwcm9wcy5yZWYpIGRlbGV0ZSBwcm9wcy5yZWY7XG4gICAgICAgICAgICBpZiAoY29tcG9uZW50Ll9fa2V5ID0gcHJvcHMua2V5KSBkZWxldGUgcHJvcHMua2V5O1xuICAgICAgICAgICAgaWYgKCFjb21wb25lbnQuYmFzZSB8fCBtb3VudEFsbCkge1xuICAgICAgICAgICAgICAgIGlmIChjb21wb25lbnQuY29tcG9uZW50V2lsbE1vdW50KSBjb21wb25lbnQuY29tcG9uZW50V2lsbE1vdW50KCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNvbXBvbmVudC5jb21wb25lbnRXaWxsUmVjZWl2ZVByb3BzKSBjb21wb25lbnQuY29tcG9uZW50V2lsbFJlY2VpdmVQcm9wcyhwcm9wcywgY29udGV4dCk7XG4gICAgICAgICAgICBpZiAoY29udGV4dCAmJiBjb250ZXh0ICE9PSBjb21wb25lbnQuY29udGV4dCkge1xuICAgICAgICAgICAgICAgIGlmICghY29tcG9uZW50LnByZXZDb250ZXh0KSBjb21wb25lbnQucHJldkNvbnRleHQgPSBjb21wb25lbnQuY29udGV4dDtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWNvbXBvbmVudC5wcmV2UHJvcHMpIGNvbXBvbmVudC5wcmV2UHJvcHMgPSBjb21wb25lbnQucHJvcHM7XG4gICAgICAgICAgICBjb21wb25lbnQucHJvcHMgPSBwcm9wcztcbiAgICAgICAgICAgIGNvbXBvbmVudC5fZGlzYWJsZSA9ICExO1xuICAgICAgICAgICAgaWYgKDAgIT09IG9wdHMpIGlmICgxID09PSBvcHRzIHx8IG9wdGlvbnMuc3luY0NvbXBvbmVudFVwZGF0ZXMgIT09ICExIHx8ICFjb21wb25lbnQuYmFzZSkgcmVuZGVyQ29tcG9uZW50KGNvbXBvbmVudCwgMSwgbW91bnRBbGwpOyBlbHNlIGVucXVldWVSZW5kZXIoY29tcG9uZW50KTtcbiAgICAgICAgICAgIGlmIChjb21wb25lbnQuX19yZWYpIGNvbXBvbmVudC5fX3JlZihjb21wb25lbnQpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHJlbmRlckNvbXBvbmVudChjb21wb25lbnQsIG9wdHMsIG1vdW50QWxsLCBpc0NoaWxkKSB7XG4gICAgICAgIGlmICghY29tcG9uZW50Ll9kaXNhYmxlKSB7XG4gICAgICAgICAgICB2YXIgc2tpcCwgcmVuZGVyZWQsIGluc3QsIGNiYXNlLCBwcm9wcyA9IGNvbXBvbmVudC5wcm9wcywgc3RhdGUgPSBjb21wb25lbnQuc3RhdGUsIGNvbnRleHQgPSBjb21wb25lbnQuY29udGV4dCwgcHJldmlvdXNQcm9wcyA9IGNvbXBvbmVudC5wcmV2UHJvcHMgfHwgcHJvcHMsIHByZXZpb3VzU3RhdGUgPSBjb21wb25lbnQucHJldlN0YXRlIHx8IHN0YXRlLCBwcmV2aW91c0NvbnRleHQgPSBjb21wb25lbnQucHJldkNvbnRleHQgfHwgY29udGV4dCwgaXNVcGRhdGUgPSBjb21wb25lbnQuYmFzZSwgbmV4dEJhc2UgPSBjb21wb25lbnQubmV4dEJhc2UsIGluaXRpYWxCYXNlID0gaXNVcGRhdGUgfHwgbmV4dEJhc2UsIGluaXRpYWxDaGlsZENvbXBvbmVudCA9IGNvbXBvbmVudC5fY29tcG9uZW50O1xuICAgICAgICAgICAgaWYgKGlzVXBkYXRlKSB7XG4gICAgICAgICAgICAgICAgY29tcG9uZW50LnByb3BzID0gcHJldmlvdXNQcm9wcztcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuc3RhdGUgPSBwcmV2aW91c1N0YXRlO1xuICAgICAgICAgICAgICAgIGNvbXBvbmVudC5jb250ZXh0ID0gcHJldmlvdXNDb250ZXh0O1xuICAgICAgICAgICAgICAgIGlmICgyICE9PSBvcHRzICYmIGNvbXBvbmVudC5zaG91bGRDb21wb25lbnRVcGRhdGUgJiYgY29tcG9uZW50LnNob3VsZENvbXBvbmVudFVwZGF0ZShwcm9wcywgc3RhdGUsIGNvbnRleHQpID09PSAhMSkgc2tpcCA9ICEwOyBlbHNlIGlmIChjb21wb25lbnQuY29tcG9uZW50V2lsbFVwZGF0ZSkgY29tcG9uZW50LmNvbXBvbmVudFdpbGxVcGRhdGUocHJvcHMsIHN0YXRlLCBjb250ZXh0KTtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQucHJvcHMgPSBwcm9wcztcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuc3RhdGUgPSBzdGF0ZTtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuY29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb21wb25lbnQucHJldlByb3BzID0gY29tcG9uZW50LnByZXZTdGF0ZSA9IGNvbXBvbmVudC5wcmV2Q29udGV4dCA9IGNvbXBvbmVudC5uZXh0QmFzZSA9IG51bGw7XG4gICAgICAgICAgICBjb21wb25lbnQuX2RpcnR5ID0gITE7XG4gICAgICAgICAgICBpZiAoIXNraXApIHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcG9uZW50LnJlbmRlcikgcmVuZGVyZWQgPSBjb21wb25lbnQucmVuZGVyKHByb3BzLCBzdGF0ZSwgY29udGV4dCk7XG4gICAgICAgICAgICAgICAgaWYgKGNvbXBvbmVudC5nZXRDaGlsZENvbnRleHQpIGNvbnRleHQgPSBleHRlbmQoY2xvbmUoY29udGV4dCksIGNvbXBvbmVudC5nZXRDaGlsZENvbnRleHQoKSk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGlzRnVuY3Rpb25hbENvbXBvbmVudChyZW5kZXJlZCkpIHJlbmRlcmVkID0gYnVpbGRGdW5jdGlvbmFsQ29tcG9uZW50KHJlbmRlcmVkLCBjb250ZXh0KTtcbiAgICAgICAgICAgICAgICB2YXIgdG9Vbm1vdW50LCBiYXNlLCBjaGlsZENvbXBvbmVudCA9IHJlbmRlcmVkICYmIHJlbmRlcmVkLm5vZGVOYW1lO1xuICAgICAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uKGNoaWxkQ29tcG9uZW50KSkge1xuICAgICAgICAgICAgICAgICAgICBpbnN0ID0gaW5pdGlhbENoaWxkQ29tcG9uZW50O1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRQcm9wcyA9IGdldE5vZGVQcm9wcyhyZW5kZXJlZCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbnN0ICYmIGluc3QuY29uc3RydWN0b3IgPT09IGNoaWxkQ29tcG9uZW50KSBzZXRDb21wb25lbnRQcm9wcyhpbnN0LCBjaGlsZFByb3BzLCAxLCBjb250ZXh0KTsgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b1VubW91bnQgPSBpbnN0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5zdCA9IGNyZWF0ZUNvbXBvbmVudChjaGlsZENvbXBvbmVudCwgY2hpbGRQcm9wcywgY29udGV4dCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnN0Lm5leHRCYXNlID0gaW5zdC5uZXh0QmFzZSB8fCBuZXh0QmFzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc3QuX3BhcmVudENvbXBvbmVudCA9IGNvbXBvbmVudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudC5fY29tcG9uZW50ID0gaW5zdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldENvbXBvbmVudFByb3BzKGluc3QsIGNoaWxkUHJvcHMsIDAsIGNvbnRleHQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyQ29tcG9uZW50KGluc3QsIDEsIG1vdW50QWxsLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYmFzZSA9IGluc3QuYmFzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBjYmFzZSA9IGluaXRpYWxCYXNlO1xuICAgICAgICAgICAgICAgICAgICB0b1VubW91bnQgPSBpbml0aWFsQ2hpbGRDb21wb25lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0b1VubW91bnQpIGNiYXNlID0gY29tcG9uZW50Ll9jb21wb25lbnQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5pdGlhbEJhc2UgfHwgMSA9PT0gb3B0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNiYXNlKSBjYmFzZS5fY29tcG9uZW50ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhc2UgPSBkaWZmKGNiYXNlLCByZW5kZXJlZCwgY29udGV4dCwgbW91bnRBbGwgfHwgIWlzVXBkYXRlLCBpbml0aWFsQmFzZSAmJiBpbml0aWFsQmFzZS5wYXJlbnROb2RlLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGluaXRpYWxCYXNlICYmIGJhc2UgIT09IGluaXRpYWxCYXNlICYmIGluc3QgIT09IGluaXRpYWxDaGlsZENvbXBvbmVudCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYmFzZVBhcmVudCA9IGluaXRpYWxCYXNlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChiYXNlUGFyZW50ICYmIGJhc2UgIT09IGJhc2VQYXJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhc2VQYXJlbnQucmVwbGFjZUNoaWxkKGJhc2UsIGluaXRpYWxCYXNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdG9Vbm1vdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdGlhbEJhc2UuX2NvbXBvbmVudCA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjb2xsZWN0Tm9kZVRyZWUoaW5pdGlhbEJhc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0b1VubW91bnQpIHVubW91bnRDb21wb25lbnQodG9Vbm1vdW50LCBiYXNlICE9PSBpbml0aWFsQmFzZSk7XG4gICAgICAgICAgICAgICAgY29tcG9uZW50LmJhc2UgPSBiYXNlO1xuICAgICAgICAgICAgICAgIGlmIChiYXNlICYmICFpc0NoaWxkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb21wb25lbnRSZWYgPSBjb21wb25lbnQsIHQgPSBjb21wb25lbnQ7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICh0ID0gdC5fcGFyZW50Q29tcG9uZW50KSAoY29tcG9uZW50UmVmID0gdCkuYmFzZSA9IGJhc2U7XG4gICAgICAgICAgICAgICAgICAgIGJhc2UuX2NvbXBvbmVudCA9IGNvbXBvbmVudFJlZjtcbiAgICAgICAgICAgICAgICAgICAgYmFzZS5fY29tcG9uZW50Q29uc3RydWN0b3IgPSBjb21wb25lbnRSZWYuY29uc3RydWN0b3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc1VwZGF0ZSB8fCBtb3VudEFsbCkgbW91bnRzLnVuc2hpZnQoY29tcG9uZW50KTsgZWxzZSBpZiAoIXNraXApIHtcbiAgICAgICAgICAgICAgICBpZiAoY29tcG9uZW50LmNvbXBvbmVudERpZFVwZGF0ZSkgY29tcG9uZW50LmNvbXBvbmVudERpZFVwZGF0ZShwcmV2aW91c1Byb3BzLCBwcmV2aW91c1N0YXRlLCBwcmV2aW91c0NvbnRleHQpO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmFmdGVyVXBkYXRlKSBvcHRpb25zLmFmdGVyVXBkYXRlKGNvbXBvbmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZm4sIGNiID0gY29tcG9uZW50Ll9yZW5kZXJDYWxsYmFja3M7XG4gICAgICAgICAgICBpZiAoY2IpIHdoaWxlIChmbiA9IGNiLnBvcCgpKSBmbi5jYWxsKGNvbXBvbmVudCk7XG4gICAgICAgICAgICBpZiAoIWRpZmZMZXZlbCAmJiAhaXNDaGlsZCkgZmx1c2hNb3VudHMoKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBidWlsZENvbXBvbmVudEZyb21WTm9kZShkb20sIHZub2RlLCBjb250ZXh0LCBtb3VudEFsbCkge1xuICAgICAgICB2YXIgYyA9IGRvbSAmJiBkb20uX2NvbXBvbmVudCwgb2xkRG9tID0gZG9tLCBpc0RpcmVjdE93bmVyID0gYyAmJiBkb20uX2NvbXBvbmVudENvbnN0cnVjdG9yID09PSB2bm9kZS5ub2RlTmFtZSwgaXNPd25lciA9IGlzRGlyZWN0T3duZXIsIHByb3BzID0gZ2V0Tm9kZVByb3BzKHZub2RlKTtcbiAgICAgICAgd2hpbGUgKGMgJiYgIWlzT3duZXIgJiYgKGMgPSBjLl9wYXJlbnRDb21wb25lbnQpKSBpc093bmVyID0gYy5jb25zdHJ1Y3RvciA9PT0gdm5vZGUubm9kZU5hbWU7XG4gICAgICAgIGlmIChjICYmIGlzT3duZXIgJiYgKCFtb3VudEFsbCB8fCBjLl9jb21wb25lbnQpKSB7XG4gICAgICAgICAgICBzZXRDb21wb25lbnRQcm9wcyhjLCBwcm9wcywgMywgY29udGV4dCwgbW91bnRBbGwpO1xuICAgICAgICAgICAgZG9tID0gYy5iYXNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGMgJiYgIWlzRGlyZWN0T3duZXIpIHtcbiAgICAgICAgICAgICAgICB1bm1vdW50Q29tcG9uZW50KGMsICEwKTtcbiAgICAgICAgICAgICAgICBkb20gPSBvbGREb20gPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYyA9IGNyZWF0ZUNvbXBvbmVudCh2bm9kZS5ub2RlTmFtZSwgcHJvcHMsIGNvbnRleHQpO1xuICAgICAgICAgICAgaWYgKGRvbSAmJiAhYy5uZXh0QmFzZSkge1xuICAgICAgICAgICAgICAgIGMubmV4dEJhc2UgPSBkb207XG4gICAgICAgICAgICAgICAgb2xkRG9tID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHNldENvbXBvbmVudFByb3BzKGMsIHByb3BzLCAxLCBjb250ZXh0LCBtb3VudEFsbCk7XG4gICAgICAgICAgICBkb20gPSBjLmJhc2U7XG4gICAgICAgICAgICBpZiAob2xkRG9tICYmIGRvbSAhPT0gb2xkRG9tKSB7XG4gICAgICAgICAgICAgICAgb2xkRG9tLl9jb21wb25lbnQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHJlY29sbGVjdE5vZGVUcmVlKG9sZERvbSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRvbTtcbiAgICB9XG4gICAgZnVuY3Rpb24gdW5tb3VudENvbXBvbmVudChjb21wb25lbnQsIHJlbW92ZSkge1xuICAgICAgICBpZiAob3B0aW9ucy5iZWZvcmVVbm1vdW50KSBvcHRpb25zLmJlZm9yZVVubW91bnQoY29tcG9uZW50KTtcbiAgICAgICAgdmFyIGJhc2UgPSBjb21wb25lbnQuYmFzZTtcbiAgICAgICAgY29tcG9uZW50Ll9kaXNhYmxlID0gITA7XG4gICAgICAgIGlmIChjb21wb25lbnQuY29tcG9uZW50V2lsbFVubW91bnQpIGNvbXBvbmVudC5jb21wb25lbnRXaWxsVW5tb3VudCgpO1xuICAgICAgICBjb21wb25lbnQuYmFzZSA9IG51bGw7XG4gICAgICAgIHZhciBpbm5lciA9IGNvbXBvbmVudC5fY29tcG9uZW50O1xuICAgICAgICBpZiAoaW5uZXIpIHVubW91bnRDb21wb25lbnQoaW5uZXIsIHJlbW92ZSk7IGVsc2UgaWYgKGJhc2UpIHtcbiAgICAgICAgICAgIGlmIChiYXNlW0FUVFJfS0VZXSAmJiBiYXNlW0FUVFJfS0VZXS5yZWYpIGJhc2VbQVRUUl9LRVldLnJlZihudWxsKTtcbiAgICAgICAgICAgIGNvbXBvbmVudC5uZXh0QmFzZSA9IGJhc2U7XG4gICAgICAgICAgICBpZiAocmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgcmVtb3ZlTm9kZShiYXNlKTtcbiAgICAgICAgICAgICAgICBjb2xsZWN0Q29tcG9uZW50KGNvbXBvbmVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZW1vdmVPcnBoYW5lZENoaWxkcmVuKGJhc2UuY2hpbGROb2RlcywgIXJlbW92ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbXBvbmVudC5fX3JlZikgY29tcG9uZW50Ll9fcmVmKG51bGwpO1xuICAgICAgICBpZiAoY29tcG9uZW50LmNvbXBvbmVudERpZFVubW91bnQpIGNvbXBvbmVudC5jb21wb25lbnREaWRVbm1vdW50KCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIENvbXBvbmVudChwcm9wcywgY29udGV4dCkge1xuICAgICAgICB0aGlzLl9kaXJ0eSA9ICEwO1xuICAgICAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICB0aGlzLnByb3BzID0gcHJvcHM7XG4gICAgICAgIGlmICghdGhpcy5zdGF0ZSkgdGhpcy5zdGF0ZSA9IHt9O1xuICAgIH1cbiAgICBmdW5jdGlvbiByZW5kZXIodm5vZGUsIHBhcmVudCwgbWVyZ2UpIHtcbiAgICAgICAgcmV0dXJuIGRpZmYobWVyZ2UsIHZub2RlLCB7fSwgITEsIHBhcmVudCk7XG4gICAgfVxuICAgIHZhciBvcHRpb25zID0ge307XG4gICAgdmFyIHN0YWNrID0gW107XG4gICAgdmFyIGxjQ2FjaGUgPSB7fTtcbiAgICB2YXIgdG9Mb3dlckNhc2UgPSBmdW5jdGlvbihzKSB7XG4gICAgICAgIHJldHVybiBsY0NhY2hlW3NdIHx8IChsY0NhY2hlW3NdID0gcy50b0xvd2VyQ2FzZSgpKTtcbiAgICB9O1xuICAgIHZhciByZXNvbHZlZCA9ICd1bmRlZmluZWQnICE9IHR5cGVvZiBQcm9taXNlICYmIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIHZhciBkZWZlciA9IHJlc29sdmVkID8gZnVuY3Rpb24oZikge1xuICAgICAgICByZXNvbHZlZC50aGVuKGYpO1xuICAgIH0gOiBzZXRUaW1lb3V0O1xuICAgIHZhciBFTVBUWSA9IHt9O1xuICAgIHZhciBBVFRSX0tFWSA9ICd1bmRlZmluZWQnICE9IHR5cGVvZiBTeW1ib2wgPyBTeW1ib2wuZm9yKCdwcmVhY3RhdHRyJykgOiAnX19wcmVhY3RhdHRyXyc7XG4gICAgdmFyIE5PTl9ESU1FTlNJT05fUFJPUFMgPSB7XG4gICAgICAgIGJveEZsZXg6IDEsXG4gICAgICAgIGJveEZsZXhHcm91cDogMSxcbiAgICAgICAgY29sdW1uQ291bnQ6IDEsXG4gICAgICAgIGZpbGxPcGFjaXR5OiAxLFxuICAgICAgICBmbGV4OiAxLFxuICAgICAgICBmbGV4R3JvdzogMSxcbiAgICAgICAgZmxleFBvc2l0aXZlOiAxLFxuICAgICAgICBmbGV4U2hyaW5rOiAxLFxuICAgICAgICBmbGV4TmVnYXRpdmU6IDEsXG4gICAgICAgIGZvbnRXZWlnaHQ6IDEsXG4gICAgICAgIGxpbmVDbGFtcDogMSxcbiAgICAgICAgbGluZUhlaWdodDogMSxcbiAgICAgICAgb3BhY2l0eTogMSxcbiAgICAgICAgb3JkZXI6IDEsXG4gICAgICAgIG9ycGhhbnM6IDEsXG4gICAgICAgIHN0cm9rZU9wYWNpdHk6IDEsXG4gICAgICAgIHdpZG93czogMSxcbiAgICAgICAgekluZGV4OiAxLFxuICAgICAgICB6b29tOiAxXG4gICAgfTtcbiAgICB2YXIgTk9OX0JVQkJMSU5HX0VWRU5UUyA9IHtcbiAgICAgICAgYmx1cjogMSxcbiAgICAgICAgZXJyb3I6IDEsXG4gICAgICAgIGZvY3VzOiAxLFxuICAgICAgICBsb2FkOiAxLFxuICAgICAgICByZXNpemU6IDEsXG4gICAgICAgIHNjcm9sbDogMVxuICAgIH07XG4gICAgdmFyIGl0ZW1zID0gW107XG4gICAgdmFyIG5vZGVzID0ge307XG4gICAgdmFyIG1vdW50cyA9IFtdO1xuICAgIHZhciBkaWZmTGV2ZWwgPSAwO1xuICAgIHZhciBpc1N2Z01vZGUgPSAhMTtcbiAgICB2YXIgY29tcG9uZW50cyA9IHt9O1xuICAgIGV4dGVuZChDb21wb25lbnQucHJvdG90eXBlLCB7XG4gICAgICAgIGxpbmtTdGF0ZTogZnVuY3Rpb24oa2V5LCBldmVudFBhdGgpIHtcbiAgICAgICAgICAgIHZhciBjID0gdGhpcy5fbGlua2VkU3RhdGVzIHx8ICh0aGlzLl9saW5rZWRTdGF0ZXMgPSB7fSk7XG4gICAgICAgICAgICByZXR1cm4gY1trZXkgKyBldmVudFBhdGhdIHx8IChjW2tleSArIGV2ZW50UGF0aF0gPSBjcmVhdGVMaW5rZWRTdGF0ZSh0aGlzLCBrZXksIGV2ZW50UGF0aCkpO1xuICAgICAgICB9LFxuICAgICAgICBzZXRTdGF0ZTogZnVuY3Rpb24oc3RhdGUsIGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgcyA9IHRoaXMuc3RhdGU7XG4gICAgICAgICAgICBpZiAoIXRoaXMucHJldlN0YXRlKSB0aGlzLnByZXZTdGF0ZSA9IGNsb25lKHMpO1xuICAgICAgICAgICAgZXh0ZW5kKHMsIGlzRnVuY3Rpb24oc3RhdGUpID8gc3RhdGUocywgdGhpcy5wcm9wcykgOiBzdGF0ZSk7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2spICh0aGlzLl9yZW5kZXJDYWxsYmFja3MgPSB0aGlzLl9yZW5kZXJDYWxsYmFja3MgfHwgW10pLnB1c2goY2FsbGJhY2spO1xuICAgICAgICAgICAgZW5xdWV1ZVJlbmRlcih0aGlzKTtcbiAgICAgICAgfSxcbiAgICAgICAgZm9yY2VVcGRhdGU6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmVuZGVyQ29tcG9uZW50KHRoaXMsIDIpO1xuICAgICAgICB9LFxuICAgICAgICByZW5kZXI6IGZ1bmN0aW9uKCkge31cbiAgICB9KTtcbiAgICBleHBvcnRzLmggPSBoO1xuICAgIGV4cG9ydHMuY2xvbmVFbGVtZW50ID0gY2xvbmVFbGVtZW50O1xuICAgIGV4cG9ydHMuQ29tcG9uZW50ID0gQ29tcG9uZW50O1xuICAgIGV4cG9ydHMucmVuZGVyID0gcmVuZGVyO1xuICAgIGV4cG9ydHMucmVyZW5kZXIgPSByZXJlbmRlcjtcbiAgICBleHBvcnRzLm9wdGlvbnMgPSBvcHRpb25zO1xufSk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1wcmVhY3QuanMubWFwIiwiJ3VzZSBzdHJpY3QnO1xuXG5pZiAoIXByb2Nlc3MudmVyc2lvbiB8fFxuICAgIHByb2Nlc3MudmVyc2lvbi5pbmRleE9mKCd2MC4nKSA9PT0gMCB8fFxuICAgIHByb2Nlc3MudmVyc2lvbi5pbmRleE9mKCd2MS4nKSA9PT0gMCAmJiBwcm9jZXNzLnZlcnNpb24uaW5kZXhPZigndjEuOC4nKSAhPT0gMCkge1xuICBtb2R1bGUuZXhwb3J0cyA9IHsgbmV4dFRpY2s6IG5leHRUaWNrIH07XG59IGVsc2Uge1xuICBtb2R1bGUuZXhwb3J0cyA9IHByb2Nlc3Ncbn1cblxuZnVuY3Rpb24gbmV4dFRpY2soZm4sIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgaWYgKHR5cGVvZiBmbiAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiY2FsbGJhY2tcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgfVxuICB2YXIgbGVuID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgdmFyIGFyZ3MsIGk7XG4gIHN3aXRjaCAobGVuKSB7XG4gIGNhc2UgMDpcbiAgY2FzZSAxOlxuICAgIHJldHVybiBwcm9jZXNzLm5leHRUaWNrKGZuKTtcbiAgY2FzZSAyOlxuICAgIHJldHVybiBwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uIGFmdGVyVGlja09uZSgpIHtcbiAgICAgIGZuLmNhbGwobnVsbCwgYXJnMSk7XG4gICAgfSk7XG4gIGNhc2UgMzpcbiAgICByZXR1cm4gcHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiBhZnRlclRpY2tUd28oKSB7XG4gICAgICBmbi5jYWxsKG51bGwsIGFyZzEsIGFyZzIpO1xuICAgIH0pO1xuICBjYXNlIDQ6XG4gICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24gYWZ0ZXJUaWNrVGhyZWUoKSB7XG4gICAgICBmbi5jYWxsKG51bGwsIGFyZzEsIGFyZzIsIGFyZzMpO1xuICAgIH0pO1xuICBkZWZhdWx0OlxuICAgIGFyZ3MgPSBuZXcgQXJyYXkobGVuIC0gMSk7XG4gICAgaSA9IDA7XG4gICAgd2hpbGUgKGkgPCBhcmdzLmxlbmd0aCkge1xuICAgICAgYXJnc1tpKytdID0gYXJndW1lbnRzW2ldO1xuICAgIH1cbiAgICByZXR1cm4gcHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiBhZnRlclRpY2soKSB7XG4gICAgICBmbi5hcHBseShudWxsLCBhcmdzKTtcbiAgICB9KTtcbiAgfVxufVxuXG4iLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuIiwiLyohIGh0dHBzOi8vbXRocy5iZS9wdW55Y29kZSB2MS40LjEgYnkgQG1hdGhpYXMgKi9cbjsoZnVuY3Rpb24ocm9vdCkge1xuXG5cdC8qKiBEZXRlY3QgZnJlZSB2YXJpYWJsZXMgKi9cblx0dmFyIGZyZWVFeHBvcnRzID0gdHlwZW9mIGV4cG9ydHMgPT0gJ29iamVjdCcgJiYgZXhwb3J0cyAmJlxuXHRcdCFleHBvcnRzLm5vZGVUeXBlICYmIGV4cG9ydHM7XG5cdHZhciBmcmVlTW9kdWxlID0gdHlwZW9mIG1vZHVsZSA9PSAnb2JqZWN0JyAmJiBtb2R1bGUgJiZcblx0XHQhbW9kdWxlLm5vZGVUeXBlICYmIG1vZHVsZTtcblx0dmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbDtcblx0aWYgKFxuXHRcdGZyZWVHbG9iYWwuZ2xvYmFsID09PSBmcmVlR2xvYmFsIHx8XG5cdFx0ZnJlZUdsb2JhbC53aW5kb3cgPT09IGZyZWVHbG9iYWwgfHxcblx0XHRmcmVlR2xvYmFsLnNlbGYgPT09IGZyZWVHbG9iYWxcblx0KSB7XG5cdFx0cm9vdCA9IGZyZWVHbG9iYWw7XG5cdH1cblxuXHQvKipcblx0ICogVGhlIGBwdW55Y29kZWAgb2JqZWN0LlxuXHQgKiBAbmFtZSBwdW55Y29kZVxuXHQgKiBAdHlwZSBPYmplY3Rcblx0ICovXG5cdHZhciBwdW55Y29kZSxcblxuXHQvKiogSGlnaGVzdCBwb3NpdGl2ZSBzaWduZWQgMzItYml0IGZsb2F0IHZhbHVlICovXG5cdG1heEludCA9IDIxNDc0ODM2NDcsIC8vIGFrYS4gMHg3RkZGRkZGRiBvciAyXjMxLTFcblxuXHQvKiogQm9vdHN0cmluZyBwYXJhbWV0ZXJzICovXG5cdGJhc2UgPSAzNixcblx0dE1pbiA9IDEsXG5cdHRNYXggPSAyNixcblx0c2tldyA9IDM4LFxuXHRkYW1wID0gNzAwLFxuXHRpbml0aWFsQmlhcyA9IDcyLFxuXHRpbml0aWFsTiA9IDEyOCwgLy8gMHg4MFxuXHRkZWxpbWl0ZXIgPSAnLScsIC8vICdcXHgyRCdcblxuXHQvKiogUmVndWxhciBleHByZXNzaW9ucyAqL1xuXHRyZWdleFB1bnljb2RlID0gL154bi0tLyxcblx0cmVnZXhOb25BU0NJSSA9IC9bXlxceDIwLVxceDdFXS8sIC8vIHVucHJpbnRhYmxlIEFTQ0lJIGNoYXJzICsgbm9uLUFTQ0lJIGNoYXJzXG5cdHJlZ2V4U2VwYXJhdG9ycyA9IC9bXFx4MkVcXHUzMDAyXFx1RkYwRVxcdUZGNjFdL2csIC8vIFJGQyAzNDkwIHNlcGFyYXRvcnNcblxuXHQvKiogRXJyb3IgbWVzc2FnZXMgKi9cblx0ZXJyb3JzID0ge1xuXHRcdCdvdmVyZmxvdyc6ICdPdmVyZmxvdzogaW5wdXQgbmVlZHMgd2lkZXIgaW50ZWdlcnMgdG8gcHJvY2VzcycsXG5cdFx0J25vdC1iYXNpYyc6ICdJbGxlZ2FsIGlucHV0ID49IDB4ODAgKG5vdCBhIGJhc2ljIGNvZGUgcG9pbnQpJyxcblx0XHQnaW52YWxpZC1pbnB1dCc6ICdJbnZhbGlkIGlucHV0J1xuXHR9LFxuXG5cdC8qKiBDb252ZW5pZW5jZSBzaG9ydGN1dHMgKi9cblx0YmFzZU1pbnVzVE1pbiA9IGJhc2UgLSB0TWluLFxuXHRmbG9vciA9IE1hdGguZmxvb3IsXG5cdHN0cmluZ0Zyb21DaGFyQ29kZSA9IFN0cmluZy5mcm9tQ2hhckNvZGUsXG5cblx0LyoqIFRlbXBvcmFyeSB2YXJpYWJsZSAqL1xuXHRrZXk7XG5cblx0LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cblx0LyoqXG5cdCAqIEEgZ2VuZXJpYyBlcnJvciB1dGlsaXR5IGZ1bmN0aW9uLlxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gdHlwZSBUaGUgZXJyb3IgdHlwZS5cblx0ICogQHJldHVybnMge0Vycm9yfSBUaHJvd3MgYSBgUmFuZ2VFcnJvcmAgd2l0aCB0aGUgYXBwbGljYWJsZSBlcnJvciBtZXNzYWdlLlxuXHQgKi9cblx0ZnVuY3Rpb24gZXJyb3IodHlwZSkge1xuXHRcdHRocm93IG5ldyBSYW5nZUVycm9yKGVycm9yc1t0eXBlXSk7XG5cdH1cblxuXHQvKipcblx0ICogQSBnZW5lcmljIGBBcnJheSNtYXBgIHV0aWxpdHkgZnVuY3Rpb24uXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0aGF0IGdldHMgY2FsbGVkIGZvciBldmVyeSBhcnJheVxuXHQgKiBpdGVtLlxuXHQgKiBAcmV0dXJucyB7QXJyYXl9IEEgbmV3IGFycmF5IG9mIHZhbHVlcyByZXR1cm5lZCBieSB0aGUgY2FsbGJhY2sgZnVuY3Rpb24uXG5cdCAqL1xuXHRmdW5jdGlvbiBtYXAoYXJyYXksIGZuKSB7XG5cdFx0dmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblx0XHR2YXIgcmVzdWx0ID0gW107XG5cdFx0d2hpbGUgKGxlbmd0aC0tKSB7XG5cdFx0XHRyZXN1bHRbbGVuZ3RoXSA9IGZuKGFycmF5W2xlbmd0aF0pO1xuXHRcdH1cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9XG5cblx0LyoqXG5cdCAqIEEgc2ltcGxlIGBBcnJheSNtYXBgLWxpa2Ugd3JhcHBlciB0byB3b3JrIHdpdGggZG9tYWluIG5hbWUgc3RyaW5ncyBvciBlbWFpbFxuXHQgKiBhZGRyZXNzZXMuXG5cdCAqIEBwcml2YXRlXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBkb21haW4gVGhlIGRvbWFpbiBuYW1lIG9yIGVtYWlsIGFkZHJlc3MuXG5cdCAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0aGF0IGdldHMgY2FsbGVkIGZvciBldmVyeVxuXHQgKiBjaGFyYWN0ZXIuXG5cdCAqIEByZXR1cm5zIHtBcnJheX0gQSBuZXcgc3RyaW5nIG9mIGNoYXJhY3RlcnMgcmV0dXJuZWQgYnkgdGhlIGNhbGxiYWNrXG5cdCAqIGZ1bmN0aW9uLlxuXHQgKi9cblx0ZnVuY3Rpb24gbWFwRG9tYWluKHN0cmluZywgZm4pIHtcblx0XHR2YXIgcGFydHMgPSBzdHJpbmcuc3BsaXQoJ0AnKTtcblx0XHR2YXIgcmVzdWx0ID0gJyc7XG5cdFx0aWYgKHBhcnRzLmxlbmd0aCA+IDEpIHtcblx0XHRcdC8vIEluIGVtYWlsIGFkZHJlc3Nlcywgb25seSB0aGUgZG9tYWluIG5hbWUgc2hvdWxkIGJlIHB1bnljb2RlZC4gTGVhdmVcblx0XHRcdC8vIHRoZSBsb2NhbCBwYXJ0IChpLmUuIGV2ZXJ5dGhpbmcgdXAgdG8gYEBgKSBpbnRhY3QuXG5cdFx0XHRyZXN1bHQgPSBwYXJ0c1swXSArICdAJztcblx0XHRcdHN0cmluZyA9IHBhcnRzWzFdO1xuXHRcdH1cblx0XHQvLyBBdm9pZCBgc3BsaXQocmVnZXgpYCBmb3IgSUU4IGNvbXBhdGliaWxpdHkuIFNlZSAjMTcuXG5cdFx0c3RyaW5nID0gc3RyaW5nLnJlcGxhY2UocmVnZXhTZXBhcmF0b3JzLCAnXFx4MkUnKTtcblx0XHR2YXIgbGFiZWxzID0gc3RyaW5nLnNwbGl0KCcuJyk7XG5cdFx0dmFyIGVuY29kZWQgPSBtYXAobGFiZWxzLCBmbikuam9pbignLicpO1xuXHRcdHJldHVybiByZXN1bHQgKyBlbmNvZGVkO1xuXHR9XG5cblx0LyoqXG5cdCAqIENyZWF0ZXMgYW4gYXJyYXkgY29udGFpbmluZyB0aGUgbnVtZXJpYyBjb2RlIHBvaW50cyBvZiBlYWNoIFVuaWNvZGVcblx0ICogY2hhcmFjdGVyIGluIHRoZSBzdHJpbmcuIFdoaWxlIEphdmFTY3JpcHQgdXNlcyBVQ1MtMiBpbnRlcm5hbGx5LFxuXHQgKiB0aGlzIGZ1bmN0aW9uIHdpbGwgY29udmVydCBhIHBhaXIgb2Ygc3Vycm9nYXRlIGhhbHZlcyAoZWFjaCBvZiB3aGljaFxuXHQgKiBVQ1MtMiBleHBvc2VzIGFzIHNlcGFyYXRlIGNoYXJhY3RlcnMpIGludG8gYSBzaW5nbGUgY29kZSBwb2ludCxcblx0ICogbWF0Y2hpbmcgVVRGLTE2LlxuXHQgKiBAc2VlIGBwdW55Y29kZS51Y3MyLmVuY29kZWBcblx0ICogQHNlZSA8aHR0cHM6Ly9tYXRoaWFzYnluZW5zLmJlL25vdGVzL2phdmFzY3JpcHQtZW5jb2Rpbmc+XG5cdCAqIEBtZW1iZXJPZiBwdW55Y29kZS51Y3MyXG5cdCAqIEBuYW1lIGRlY29kZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gc3RyaW5nIFRoZSBVbmljb2RlIGlucHV0IHN0cmluZyAoVUNTLTIpLlxuXHQgKiBAcmV0dXJucyB7QXJyYXl9IFRoZSBuZXcgYXJyYXkgb2YgY29kZSBwb2ludHMuXG5cdCAqL1xuXHRmdW5jdGlvbiB1Y3MyZGVjb2RlKHN0cmluZykge1xuXHRcdHZhciBvdXRwdXQgPSBbXSxcblx0XHQgICAgY291bnRlciA9IDAsXG5cdFx0ICAgIGxlbmd0aCA9IHN0cmluZy5sZW5ndGgsXG5cdFx0ICAgIHZhbHVlLFxuXHRcdCAgICBleHRyYTtcblx0XHR3aGlsZSAoY291bnRlciA8IGxlbmd0aCkge1xuXHRcdFx0dmFsdWUgPSBzdHJpbmcuY2hhckNvZGVBdChjb3VudGVyKyspO1xuXHRcdFx0aWYgKHZhbHVlID49IDB4RDgwMCAmJiB2YWx1ZSA8PSAweERCRkYgJiYgY291bnRlciA8IGxlbmd0aCkge1xuXHRcdFx0XHQvLyBoaWdoIHN1cnJvZ2F0ZSwgYW5kIHRoZXJlIGlzIGEgbmV4dCBjaGFyYWN0ZXJcblx0XHRcdFx0ZXh0cmEgPSBzdHJpbmcuY2hhckNvZGVBdChjb3VudGVyKyspO1xuXHRcdFx0XHRpZiAoKGV4dHJhICYgMHhGQzAwKSA9PSAweERDMDApIHsgLy8gbG93IHN1cnJvZ2F0ZVxuXHRcdFx0XHRcdG91dHB1dC5wdXNoKCgodmFsdWUgJiAweDNGRikgPDwgMTApICsgKGV4dHJhICYgMHgzRkYpICsgMHgxMDAwMCk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0Ly8gdW5tYXRjaGVkIHN1cnJvZ2F0ZTsgb25seSBhcHBlbmQgdGhpcyBjb2RlIHVuaXQsIGluIGNhc2UgdGhlIG5leHRcblx0XHRcdFx0XHQvLyBjb2RlIHVuaXQgaXMgdGhlIGhpZ2ggc3Vycm9nYXRlIG9mIGEgc3Vycm9nYXRlIHBhaXJcblx0XHRcdFx0XHRvdXRwdXQucHVzaCh2YWx1ZSk7XG5cdFx0XHRcdFx0Y291bnRlci0tO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvdXRwdXQucHVzaCh2YWx1ZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBvdXRwdXQ7XG5cdH1cblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIHN0cmluZyBiYXNlZCBvbiBhbiBhcnJheSBvZiBudW1lcmljIGNvZGUgcG9pbnRzLlxuXHQgKiBAc2VlIGBwdW55Y29kZS51Y3MyLmRlY29kZWBcblx0ICogQG1lbWJlck9mIHB1bnljb2RlLnVjczJcblx0ICogQG5hbWUgZW5jb2RlXG5cdCAqIEBwYXJhbSB7QXJyYXl9IGNvZGVQb2ludHMgVGhlIGFycmF5IG9mIG51bWVyaWMgY29kZSBwb2ludHMuXG5cdCAqIEByZXR1cm5zIHtTdHJpbmd9IFRoZSBuZXcgVW5pY29kZSBzdHJpbmcgKFVDUy0yKS5cblx0ICovXG5cdGZ1bmN0aW9uIHVjczJlbmNvZGUoYXJyYXkpIHtcblx0XHRyZXR1cm4gbWFwKGFycmF5LCBmdW5jdGlvbih2YWx1ZSkge1xuXHRcdFx0dmFyIG91dHB1dCA9ICcnO1xuXHRcdFx0aWYgKHZhbHVlID4gMHhGRkZGKSB7XG5cdFx0XHRcdHZhbHVlIC09IDB4MTAwMDA7XG5cdFx0XHRcdG91dHB1dCArPSBzdHJpbmdGcm9tQ2hhckNvZGUodmFsdWUgPj4+IDEwICYgMHgzRkYgfCAweEQ4MDApO1xuXHRcdFx0XHR2YWx1ZSA9IDB4REMwMCB8IHZhbHVlICYgMHgzRkY7XG5cdFx0XHR9XG5cdFx0XHRvdXRwdXQgKz0gc3RyaW5nRnJvbUNoYXJDb2RlKHZhbHVlKTtcblx0XHRcdHJldHVybiBvdXRwdXQ7XG5cdFx0fSkuam9pbignJyk7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYSBiYXNpYyBjb2RlIHBvaW50IGludG8gYSBkaWdpdC9pbnRlZ2VyLlxuXHQgKiBAc2VlIGBkaWdpdFRvQmFzaWMoKWBcblx0ICogQHByaXZhdGVcblx0ICogQHBhcmFtIHtOdW1iZXJ9IGNvZGVQb2ludCBUaGUgYmFzaWMgbnVtZXJpYyBjb2RlIHBvaW50IHZhbHVlLlxuXHQgKiBAcmV0dXJucyB7TnVtYmVyfSBUaGUgbnVtZXJpYyB2YWx1ZSBvZiBhIGJhc2ljIGNvZGUgcG9pbnQgKGZvciB1c2UgaW5cblx0ICogcmVwcmVzZW50aW5nIGludGVnZXJzKSBpbiB0aGUgcmFuZ2UgYDBgIHRvIGBiYXNlIC0gMWAsIG9yIGBiYXNlYCBpZlxuXHQgKiB0aGUgY29kZSBwb2ludCBkb2VzIG5vdCByZXByZXNlbnQgYSB2YWx1ZS5cblx0ICovXG5cdGZ1bmN0aW9uIGJhc2ljVG9EaWdpdChjb2RlUG9pbnQpIHtcblx0XHRpZiAoY29kZVBvaW50IC0gNDggPCAxMCkge1xuXHRcdFx0cmV0dXJuIGNvZGVQb2ludCAtIDIyO1xuXHRcdH1cblx0XHRpZiAoY29kZVBvaW50IC0gNjUgPCAyNikge1xuXHRcdFx0cmV0dXJuIGNvZGVQb2ludCAtIDY1O1xuXHRcdH1cblx0XHRpZiAoY29kZVBvaW50IC0gOTcgPCAyNikge1xuXHRcdFx0cmV0dXJuIGNvZGVQb2ludCAtIDk3O1xuXHRcdH1cblx0XHRyZXR1cm4gYmFzZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhIGRpZ2l0L2ludGVnZXIgaW50byBhIGJhc2ljIGNvZGUgcG9pbnQuXG5cdCAqIEBzZWUgYGJhc2ljVG9EaWdpdCgpYFxuXHQgKiBAcHJpdmF0ZVxuXHQgKiBAcGFyYW0ge051bWJlcn0gZGlnaXQgVGhlIG51bWVyaWMgdmFsdWUgb2YgYSBiYXNpYyBjb2RlIHBvaW50LlxuXHQgKiBAcmV0dXJucyB7TnVtYmVyfSBUaGUgYmFzaWMgY29kZSBwb2ludCB3aG9zZSB2YWx1ZSAod2hlbiB1c2VkIGZvclxuXHQgKiByZXByZXNlbnRpbmcgaW50ZWdlcnMpIGlzIGBkaWdpdGAsIHdoaWNoIG5lZWRzIHRvIGJlIGluIHRoZSByYW5nZVxuXHQgKiBgMGAgdG8gYGJhc2UgLSAxYC4gSWYgYGZsYWdgIGlzIG5vbi16ZXJvLCB0aGUgdXBwZXJjYXNlIGZvcm0gaXNcblx0ICogdXNlZDsgZWxzZSwgdGhlIGxvd2VyY2FzZSBmb3JtIGlzIHVzZWQuIFRoZSBiZWhhdmlvciBpcyB1bmRlZmluZWRcblx0ICogaWYgYGZsYWdgIGlzIG5vbi16ZXJvIGFuZCBgZGlnaXRgIGhhcyBubyB1cHBlcmNhc2UgZm9ybS5cblx0ICovXG5cdGZ1bmN0aW9uIGRpZ2l0VG9CYXNpYyhkaWdpdCwgZmxhZykge1xuXHRcdC8vICAwLi4yNSBtYXAgdG8gQVNDSUkgYS4ueiBvciBBLi5aXG5cdFx0Ly8gMjYuLjM1IG1hcCB0byBBU0NJSSAwLi45XG5cdFx0cmV0dXJuIGRpZ2l0ICsgMjIgKyA3NSAqIChkaWdpdCA8IDI2KSAtICgoZmxhZyAhPSAwKSA8PCA1KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBCaWFzIGFkYXB0YXRpb24gZnVuY3Rpb24gYXMgcGVyIHNlY3Rpb24gMy40IG9mIFJGQyAzNDkyLlxuXHQgKiBodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjMzQ5MiNzZWN0aW9uLTMuNFxuXHQgKiBAcHJpdmF0ZVxuXHQgKi9cblx0ZnVuY3Rpb24gYWRhcHQoZGVsdGEsIG51bVBvaW50cywgZmlyc3RUaW1lKSB7XG5cdFx0dmFyIGsgPSAwO1xuXHRcdGRlbHRhID0gZmlyc3RUaW1lID8gZmxvb3IoZGVsdGEgLyBkYW1wKSA6IGRlbHRhID4+IDE7XG5cdFx0ZGVsdGEgKz0gZmxvb3IoZGVsdGEgLyBudW1Qb2ludHMpO1xuXHRcdGZvciAoLyogbm8gaW5pdGlhbGl6YXRpb24gKi87IGRlbHRhID4gYmFzZU1pbnVzVE1pbiAqIHRNYXggPj4gMTsgayArPSBiYXNlKSB7XG5cdFx0XHRkZWx0YSA9IGZsb29yKGRlbHRhIC8gYmFzZU1pbnVzVE1pbik7XG5cdFx0fVxuXHRcdHJldHVybiBmbG9vcihrICsgKGJhc2VNaW51c1RNaW4gKyAxKSAqIGRlbHRhIC8gKGRlbHRhICsgc2tldykpO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgUHVueWNvZGUgc3RyaW5nIG9mIEFTQ0lJLW9ubHkgc3ltYm9scyB0byBhIHN0cmluZyBvZiBVbmljb2RlXG5cdCAqIHN5bWJvbHMuXG5cdCAqIEBtZW1iZXJPZiBwdW55Y29kZVxuXHQgKiBAcGFyYW0ge1N0cmluZ30gaW5wdXQgVGhlIFB1bnljb2RlIHN0cmluZyBvZiBBU0NJSS1vbmx5IHN5bWJvbHMuXG5cdCAqIEByZXR1cm5zIHtTdHJpbmd9IFRoZSByZXN1bHRpbmcgc3RyaW5nIG9mIFVuaWNvZGUgc3ltYm9scy5cblx0ICovXG5cdGZ1bmN0aW9uIGRlY29kZShpbnB1dCkge1xuXHRcdC8vIERvbid0IHVzZSBVQ1MtMlxuXHRcdHZhciBvdXRwdXQgPSBbXSxcblx0XHQgICAgaW5wdXRMZW5ndGggPSBpbnB1dC5sZW5ndGgsXG5cdFx0ICAgIG91dCxcblx0XHQgICAgaSA9IDAsXG5cdFx0ICAgIG4gPSBpbml0aWFsTixcblx0XHQgICAgYmlhcyA9IGluaXRpYWxCaWFzLFxuXHRcdCAgICBiYXNpYyxcblx0XHQgICAgaixcblx0XHQgICAgaW5kZXgsXG5cdFx0ICAgIG9sZGksXG5cdFx0ICAgIHcsXG5cdFx0ICAgIGssXG5cdFx0ICAgIGRpZ2l0LFxuXHRcdCAgICB0LFxuXHRcdCAgICAvKiogQ2FjaGVkIGNhbGN1bGF0aW9uIHJlc3VsdHMgKi9cblx0XHQgICAgYmFzZU1pbnVzVDtcblxuXHRcdC8vIEhhbmRsZSB0aGUgYmFzaWMgY29kZSBwb2ludHM6IGxldCBgYmFzaWNgIGJlIHRoZSBudW1iZXIgb2YgaW5wdXQgY29kZVxuXHRcdC8vIHBvaW50cyBiZWZvcmUgdGhlIGxhc3QgZGVsaW1pdGVyLCBvciBgMGAgaWYgdGhlcmUgaXMgbm9uZSwgdGhlbiBjb3B5XG5cdFx0Ly8gdGhlIGZpcnN0IGJhc2ljIGNvZGUgcG9pbnRzIHRvIHRoZSBvdXRwdXQuXG5cblx0XHRiYXNpYyA9IGlucHV0Lmxhc3RJbmRleE9mKGRlbGltaXRlcik7XG5cdFx0aWYgKGJhc2ljIDwgMCkge1xuXHRcdFx0YmFzaWMgPSAwO1xuXHRcdH1cblxuXHRcdGZvciAoaiA9IDA7IGogPCBiYXNpYzsgKytqKSB7XG5cdFx0XHQvLyBpZiBpdCdzIG5vdCBhIGJhc2ljIGNvZGUgcG9pbnRcblx0XHRcdGlmIChpbnB1dC5jaGFyQ29kZUF0KGopID49IDB4ODApIHtcblx0XHRcdFx0ZXJyb3IoJ25vdC1iYXNpYycpO1xuXHRcdFx0fVxuXHRcdFx0b3V0cHV0LnB1c2goaW5wdXQuY2hhckNvZGVBdChqKSk7XG5cdFx0fVxuXG5cdFx0Ly8gTWFpbiBkZWNvZGluZyBsb29wOiBzdGFydCBqdXN0IGFmdGVyIHRoZSBsYXN0IGRlbGltaXRlciBpZiBhbnkgYmFzaWMgY29kZVxuXHRcdC8vIHBvaW50cyB3ZXJlIGNvcGllZDsgc3RhcnQgYXQgdGhlIGJlZ2lubmluZyBvdGhlcndpc2UuXG5cblx0XHRmb3IgKGluZGV4ID0gYmFzaWMgPiAwID8gYmFzaWMgKyAxIDogMDsgaW5kZXggPCBpbnB1dExlbmd0aDsgLyogbm8gZmluYWwgZXhwcmVzc2lvbiAqLykge1xuXG5cdFx0XHQvLyBgaW5kZXhgIGlzIHRoZSBpbmRleCBvZiB0aGUgbmV4dCBjaGFyYWN0ZXIgdG8gYmUgY29uc3VtZWQuXG5cdFx0XHQvLyBEZWNvZGUgYSBnZW5lcmFsaXplZCB2YXJpYWJsZS1sZW5ndGggaW50ZWdlciBpbnRvIGBkZWx0YWAsXG5cdFx0XHQvLyB3aGljaCBnZXRzIGFkZGVkIHRvIGBpYC4gVGhlIG92ZXJmbG93IGNoZWNraW5nIGlzIGVhc2llclxuXHRcdFx0Ly8gaWYgd2UgaW5jcmVhc2UgYGlgIGFzIHdlIGdvLCB0aGVuIHN1YnRyYWN0IG9mZiBpdHMgc3RhcnRpbmdcblx0XHRcdC8vIHZhbHVlIGF0IHRoZSBlbmQgdG8gb2J0YWluIGBkZWx0YWAuXG5cdFx0XHRmb3IgKG9sZGkgPSBpLCB3ID0gMSwgayA9IGJhc2U7IC8qIG5vIGNvbmRpdGlvbiAqLzsgayArPSBiYXNlKSB7XG5cblx0XHRcdFx0aWYgKGluZGV4ID49IGlucHV0TGVuZ3RoKSB7XG5cdFx0XHRcdFx0ZXJyb3IoJ2ludmFsaWQtaW5wdXQnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRpZ2l0ID0gYmFzaWNUb0RpZ2l0KGlucHV0LmNoYXJDb2RlQXQoaW5kZXgrKykpO1xuXG5cdFx0XHRcdGlmIChkaWdpdCA+PSBiYXNlIHx8IGRpZ2l0ID4gZmxvb3IoKG1heEludCAtIGkpIC8gdykpIHtcblx0XHRcdFx0XHRlcnJvcignb3ZlcmZsb3cnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGkgKz0gZGlnaXQgKiB3O1xuXHRcdFx0XHR0ID0gayA8PSBiaWFzID8gdE1pbiA6IChrID49IGJpYXMgKyB0TWF4ID8gdE1heCA6IGsgLSBiaWFzKTtcblxuXHRcdFx0XHRpZiAoZGlnaXQgPCB0KSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRiYXNlTWludXNUID0gYmFzZSAtIHQ7XG5cdFx0XHRcdGlmICh3ID4gZmxvb3IobWF4SW50IC8gYmFzZU1pbnVzVCkpIHtcblx0XHRcdFx0XHRlcnJvcignb3ZlcmZsb3cnKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHcgKj0gYmFzZU1pbnVzVDtcblxuXHRcdFx0fVxuXG5cdFx0XHRvdXQgPSBvdXRwdXQubGVuZ3RoICsgMTtcblx0XHRcdGJpYXMgPSBhZGFwdChpIC0gb2xkaSwgb3V0LCBvbGRpID09IDApO1xuXG5cdFx0XHQvLyBgaWAgd2FzIHN1cHBvc2VkIHRvIHdyYXAgYXJvdW5kIGZyb20gYG91dGAgdG8gYDBgLFxuXHRcdFx0Ly8gaW5jcmVtZW50aW5nIGBuYCBlYWNoIHRpbWUsIHNvIHdlJ2xsIGZpeCB0aGF0IG5vdzpcblx0XHRcdGlmIChmbG9vcihpIC8gb3V0KSA+IG1heEludCAtIG4pIHtcblx0XHRcdFx0ZXJyb3IoJ292ZXJmbG93Jyk7XG5cdFx0XHR9XG5cblx0XHRcdG4gKz0gZmxvb3IoaSAvIG91dCk7XG5cdFx0XHRpICU9IG91dDtcblxuXHRcdFx0Ly8gSW5zZXJ0IGBuYCBhdCBwb3NpdGlvbiBgaWAgb2YgdGhlIG91dHB1dFxuXHRcdFx0b3V0cHV0LnNwbGljZShpKyssIDAsIG4pO1xuXG5cdFx0fVxuXG5cdFx0cmV0dXJuIHVjczJlbmNvZGUob3V0cHV0KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyBhIHN0cmluZyBvZiBVbmljb2RlIHN5bWJvbHMgKGUuZy4gYSBkb21haW4gbmFtZSBsYWJlbCkgdG8gYVxuXHQgKiBQdW55Y29kZSBzdHJpbmcgb2YgQVNDSUktb25seSBzeW1ib2xzLlxuXHQgKiBAbWVtYmVyT2YgcHVueWNvZGVcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFRoZSBzdHJpbmcgb2YgVW5pY29kZSBzeW1ib2xzLlxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgcmVzdWx0aW5nIFB1bnljb2RlIHN0cmluZyBvZiBBU0NJSS1vbmx5IHN5bWJvbHMuXG5cdCAqL1xuXHRmdW5jdGlvbiBlbmNvZGUoaW5wdXQpIHtcblx0XHR2YXIgbixcblx0XHQgICAgZGVsdGEsXG5cdFx0ICAgIGhhbmRsZWRDUENvdW50LFxuXHRcdCAgICBiYXNpY0xlbmd0aCxcblx0XHQgICAgYmlhcyxcblx0XHQgICAgaixcblx0XHQgICAgbSxcblx0XHQgICAgcSxcblx0XHQgICAgayxcblx0XHQgICAgdCxcblx0XHQgICAgY3VycmVudFZhbHVlLFxuXHRcdCAgICBvdXRwdXQgPSBbXSxcblx0XHQgICAgLyoqIGBpbnB1dExlbmd0aGAgd2lsbCBob2xkIHRoZSBudW1iZXIgb2YgY29kZSBwb2ludHMgaW4gYGlucHV0YC4gKi9cblx0XHQgICAgaW5wdXRMZW5ndGgsXG5cdFx0ICAgIC8qKiBDYWNoZWQgY2FsY3VsYXRpb24gcmVzdWx0cyAqL1xuXHRcdCAgICBoYW5kbGVkQ1BDb3VudFBsdXNPbmUsXG5cdFx0ICAgIGJhc2VNaW51c1QsXG5cdFx0ICAgIHFNaW51c1Q7XG5cblx0XHQvLyBDb252ZXJ0IHRoZSBpbnB1dCBpbiBVQ1MtMiB0byBVbmljb2RlXG5cdFx0aW5wdXQgPSB1Y3MyZGVjb2RlKGlucHV0KTtcblxuXHRcdC8vIENhY2hlIHRoZSBsZW5ndGhcblx0XHRpbnB1dExlbmd0aCA9IGlucHV0Lmxlbmd0aDtcblxuXHRcdC8vIEluaXRpYWxpemUgdGhlIHN0YXRlXG5cdFx0biA9IGluaXRpYWxOO1xuXHRcdGRlbHRhID0gMDtcblx0XHRiaWFzID0gaW5pdGlhbEJpYXM7XG5cblx0XHQvLyBIYW5kbGUgdGhlIGJhc2ljIGNvZGUgcG9pbnRzXG5cdFx0Zm9yIChqID0gMDsgaiA8IGlucHV0TGVuZ3RoOyArK2opIHtcblx0XHRcdGN1cnJlbnRWYWx1ZSA9IGlucHV0W2pdO1xuXHRcdFx0aWYgKGN1cnJlbnRWYWx1ZSA8IDB4ODApIHtcblx0XHRcdFx0b3V0cHV0LnB1c2goc3RyaW5nRnJvbUNoYXJDb2RlKGN1cnJlbnRWYWx1ZSkpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGhhbmRsZWRDUENvdW50ID0gYmFzaWNMZW5ndGggPSBvdXRwdXQubGVuZ3RoO1xuXG5cdFx0Ly8gYGhhbmRsZWRDUENvdW50YCBpcyB0aGUgbnVtYmVyIG9mIGNvZGUgcG9pbnRzIHRoYXQgaGF2ZSBiZWVuIGhhbmRsZWQ7XG5cdFx0Ly8gYGJhc2ljTGVuZ3RoYCBpcyB0aGUgbnVtYmVyIG9mIGJhc2ljIGNvZGUgcG9pbnRzLlxuXG5cdFx0Ly8gRmluaXNoIHRoZSBiYXNpYyBzdHJpbmcgLSBpZiBpdCBpcyBub3QgZW1wdHkgLSB3aXRoIGEgZGVsaW1pdGVyXG5cdFx0aWYgKGJhc2ljTGVuZ3RoKSB7XG5cdFx0XHRvdXRwdXQucHVzaChkZWxpbWl0ZXIpO1xuXHRcdH1cblxuXHRcdC8vIE1haW4gZW5jb2RpbmcgbG9vcDpcblx0XHR3aGlsZSAoaGFuZGxlZENQQ291bnQgPCBpbnB1dExlbmd0aCkge1xuXG5cdFx0XHQvLyBBbGwgbm9uLWJhc2ljIGNvZGUgcG9pbnRzIDwgbiBoYXZlIGJlZW4gaGFuZGxlZCBhbHJlYWR5LiBGaW5kIHRoZSBuZXh0XG5cdFx0XHQvLyBsYXJnZXIgb25lOlxuXHRcdFx0Zm9yIChtID0gbWF4SW50LCBqID0gMDsgaiA8IGlucHV0TGVuZ3RoOyArK2opIHtcblx0XHRcdFx0Y3VycmVudFZhbHVlID0gaW5wdXRbal07XG5cdFx0XHRcdGlmIChjdXJyZW50VmFsdWUgPj0gbiAmJiBjdXJyZW50VmFsdWUgPCBtKSB7XG5cdFx0XHRcdFx0bSA9IGN1cnJlbnRWYWx1ZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBJbmNyZWFzZSBgZGVsdGFgIGVub3VnaCB0byBhZHZhbmNlIHRoZSBkZWNvZGVyJ3MgPG4saT4gc3RhdGUgdG8gPG0sMD4sXG5cdFx0XHQvLyBidXQgZ3VhcmQgYWdhaW5zdCBvdmVyZmxvd1xuXHRcdFx0aGFuZGxlZENQQ291bnRQbHVzT25lID0gaGFuZGxlZENQQ291bnQgKyAxO1xuXHRcdFx0aWYgKG0gLSBuID4gZmxvb3IoKG1heEludCAtIGRlbHRhKSAvIGhhbmRsZWRDUENvdW50UGx1c09uZSkpIHtcblx0XHRcdFx0ZXJyb3IoJ292ZXJmbG93Jyk7XG5cdFx0XHR9XG5cblx0XHRcdGRlbHRhICs9IChtIC0gbikgKiBoYW5kbGVkQ1BDb3VudFBsdXNPbmU7XG5cdFx0XHRuID0gbTtcblxuXHRcdFx0Zm9yIChqID0gMDsgaiA8IGlucHV0TGVuZ3RoOyArK2opIHtcblx0XHRcdFx0Y3VycmVudFZhbHVlID0gaW5wdXRbal07XG5cblx0XHRcdFx0aWYgKGN1cnJlbnRWYWx1ZSA8IG4gJiYgKytkZWx0YSA+IG1heEludCkge1xuXHRcdFx0XHRcdGVycm9yKCdvdmVyZmxvdycpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKGN1cnJlbnRWYWx1ZSA9PSBuKSB7XG5cdFx0XHRcdFx0Ly8gUmVwcmVzZW50IGRlbHRhIGFzIGEgZ2VuZXJhbGl6ZWQgdmFyaWFibGUtbGVuZ3RoIGludGVnZXJcblx0XHRcdFx0XHRmb3IgKHEgPSBkZWx0YSwgayA9IGJhc2U7IC8qIG5vIGNvbmRpdGlvbiAqLzsgayArPSBiYXNlKSB7XG5cdFx0XHRcdFx0XHR0ID0gayA8PSBiaWFzID8gdE1pbiA6IChrID49IGJpYXMgKyB0TWF4ID8gdE1heCA6IGsgLSBiaWFzKTtcblx0XHRcdFx0XHRcdGlmIChxIDwgdCkge1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHFNaW51c1QgPSBxIC0gdDtcblx0XHRcdFx0XHRcdGJhc2VNaW51c1QgPSBiYXNlIC0gdDtcblx0XHRcdFx0XHRcdG91dHB1dC5wdXNoKFxuXHRcdFx0XHRcdFx0XHRzdHJpbmdGcm9tQ2hhckNvZGUoZGlnaXRUb0Jhc2ljKHQgKyBxTWludXNUICUgYmFzZU1pbnVzVCwgMCkpXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0cSA9IGZsb29yKHFNaW51c1QgLyBiYXNlTWludXNUKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRvdXRwdXQucHVzaChzdHJpbmdGcm9tQ2hhckNvZGUoZGlnaXRUb0Jhc2ljKHEsIDApKSk7XG5cdFx0XHRcdFx0YmlhcyA9IGFkYXB0KGRlbHRhLCBoYW5kbGVkQ1BDb3VudFBsdXNPbmUsIGhhbmRsZWRDUENvdW50ID09IGJhc2ljTGVuZ3RoKTtcblx0XHRcdFx0XHRkZWx0YSA9IDA7XG5cdFx0XHRcdFx0KytoYW5kbGVkQ1BDb3VudDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQrK2RlbHRhO1xuXHRcdFx0KytuO1xuXG5cdFx0fVxuXHRcdHJldHVybiBvdXRwdXQuam9pbignJyk7XG5cdH1cblxuXHQvKipcblx0ICogQ29udmVydHMgYSBQdW55Y29kZSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgZG9tYWluIG5hbWUgb3IgYW4gZW1haWwgYWRkcmVzc1xuXHQgKiB0byBVbmljb2RlLiBPbmx5IHRoZSBQdW55Y29kZWQgcGFydHMgb2YgdGhlIGlucHV0IHdpbGwgYmUgY29udmVydGVkLCBpLmUuXG5cdCAqIGl0IGRvZXNuJ3QgbWF0dGVyIGlmIHlvdSBjYWxsIGl0IG9uIGEgc3RyaW5nIHRoYXQgaGFzIGFscmVhZHkgYmVlblxuXHQgKiBjb252ZXJ0ZWQgdG8gVW5pY29kZS5cblx0ICogQG1lbWJlck9mIHB1bnljb2RlXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSBpbnB1dCBUaGUgUHVueWNvZGVkIGRvbWFpbiBuYW1lIG9yIGVtYWlsIGFkZHJlc3MgdG9cblx0ICogY29udmVydCB0byBVbmljb2RlLlxuXHQgKiBAcmV0dXJucyB7U3RyaW5nfSBUaGUgVW5pY29kZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgZ2l2ZW4gUHVueWNvZGVcblx0ICogc3RyaW5nLlxuXHQgKi9cblx0ZnVuY3Rpb24gdG9Vbmljb2RlKGlucHV0KSB7XG5cdFx0cmV0dXJuIG1hcERvbWFpbihpbnB1dCwgZnVuY3Rpb24oc3RyaW5nKSB7XG5cdFx0XHRyZXR1cm4gcmVnZXhQdW55Y29kZS50ZXN0KHN0cmluZylcblx0XHRcdFx0PyBkZWNvZGUoc3RyaW5nLnNsaWNlKDQpLnRvTG93ZXJDYXNlKCkpXG5cdFx0XHRcdDogc3RyaW5nO1xuXHRcdH0pO1xuXHR9XG5cblx0LyoqXG5cdCAqIENvbnZlcnRzIGEgVW5pY29kZSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgZG9tYWluIG5hbWUgb3IgYW4gZW1haWwgYWRkcmVzcyB0b1xuXHQgKiBQdW55Y29kZS4gT25seSB0aGUgbm9uLUFTQ0lJIHBhcnRzIG9mIHRoZSBkb21haW4gbmFtZSB3aWxsIGJlIGNvbnZlcnRlZCxcblx0ICogaS5lLiBpdCBkb2Vzbid0IG1hdHRlciBpZiB5b3UgY2FsbCBpdCB3aXRoIGEgZG9tYWluIHRoYXQncyBhbHJlYWR5IGluXG5cdCAqIEFTQ0lJLlxuXHQgKiBAbWVtYmVyT2YgcHVueWNvZGVcblx0ICogQHBhcmFtIHtTdHJpbmd9IGlucHV0IFRoZSBkb21haW4gbmFtZSBvciBlbWFpbCBhZGRyZXNzIHRvIGNvbnZlcnQsIGFzIGFcblx0ICogVW5pY29kZSBzdHJpbmcuXG5cdCAqIEByZXR1cm5zIHtTdHJpbmd9IFRoZSBQdW55Y29kZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgZ2l2ZW4gZG9tYWluIG5hbWUgb3Jcblx0ICogZW1haWwgYWRkcmVzcy5cblx0ICovXG5cdGZ1bmN0aW9uIHRvQVNDSUkoaW5wdXQpIHtcblx0XHRyZXR1cm4gbWFwRG9tYWluKGlucHV0LCBmdW5jdGlvbihzdHJpbmcpIHtcblx0XHRcdHJldHVybiByZWdleE5vbkFTQ0lJLnRlc3Qoc3RyaW5nKVxuXHRcdFx0XHQ/ICd4bi0tJyArIGVuY29kZShzdHJpbmcpXG5cdFx0XHRcdDogc3RyaW5nO1xuXHRcdH0pO1xuXHR9XG5cblx0LyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cblx0LyoqIERlZmluZSB0aGUgcHVibGljIEFQSSAqL1xuXHRwdW55Y29kZSA9IHtcblx0XHQvKipcblx0XHQgKiBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGN1cnJlbnQgUHVueWNvZGUuanMgdmVyc2lvbiBudW1iZXIuXG5cdFx0ICogQG1lbWJlck9mIHB1bnljb2RlXG5cdFx0ICogQHR5cGUgU3RyaW5nXG5cdFx0ICovXG5cdFx0J3ZlcnNpb24nOiAnMS40LjEnLFxuXHRcdC8qKlxuXHRcdCAqIEFuIG9iamVjdCBvZiBtZXRob2RzIHRvIGNvbnZlcnQgZnJvbSBKYXZhU2NyaXB0J3MgaW50ZXJuYWwgY2hhcmFjdGVyXG5cdFx0ICogcmVwcmVzZW50YXRpb24gKFVDUy0yKSB0byBVbmljb2RlIGNvZGUgcG9pbnRzLCBhbmQgYmFjay5cblx0XHQgKiBAc2VlIDxodHRwczovL21hdGhpYXNieW5lbnMuYmUvbm90ZXMvamF2YXNjcmlwdC1lbmNvZGluZz5cblx0XHQgKiBAbWVtYmVyT2YgcHVueWNvZGVcblx0XHQgKiBAdHlwZSBPYmplY3Rcblx0XHQgKi9cblx0XHQndWNzMic6IHtcblx0XHRcdCdkZWNvZGUnOiB1Y3MyZGVjb2RlLFxuXHRcdFx0J2VuY29kZSc6IHVjczJlbmNvZGVcblx0XHR9LFxuXHRcdCdkZWNvZGUnOiBkZWNvZGUsXG5cdFx0J2VuY29kZSc6IGVuY29kZSxcblx0XHQndG9BU0NJSSc6IHRvQVNDSUksXG5cdFx0J3RvVW5pY29kZSc6IHRvVW5pY29kZVxuXHR9O1xuXG5cdC8qKiBFeHBvc2UgYHB1bnljb2RlYCAqL1xuXHQvLyBTb21lIEFNRCBidWlsZCBvcHRpbWl6ZXJzLCBsaWtlIHIuanMsIGNoZWNrIGZvciBzcGVjaWZpYyBjb25kaXRpb24gcGF0dGVybnNcblx0Ly8gbGlrZSB0aGUgZm9sbG93aW5nOlxuXHRpZiAoXG5cdFx0dHlwZW9mIGRlZmluZSA9PSAnZnVuY3Rpb24nICYmXG5cdFx0dHlwZW9mIGRlZmluZS5hbWQgPT0gJ29iamVjdCcgJiZcblx0XHRkZWZpbmUuYW1kXG5cdCkge1xuXHRcdGRlZmluZSgncHVueWNvZGUnLCBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBwdW55Y29kZTtcblx0XHR9KTtcblx0fSBlbHNlIGlmIChmcmVlRXhwb3J0cyAmJiBmcmVlTW9kdWxlKSB7XG5cdFx0aWYgKG1vZHVsZS5leHBvcnRzID09IGZyZWVFeHBvcnRzKSB7XG5cdFx0XHQvLyBpbiBOb2RlLmpzLCBpby5qcywgb3IgUmluZ29KUyB2MC44LjArXG5cdFx0XHRmcmVlTW9kdWxlLmV4cG9ydHMgPSBwdW55Y29kZTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gaW4gTmFyd2hhbCBvciBSaW5nb0pTIHYwLjcuMC1cblx0XHRcdGZvciAoa2V5IGluIHB1bnljb2RlKSB7XG5cdFx0XHRcdHB1bnljb2RlLmhhc093blByb3BlcnR5KGtleSkgJiYgKGZyZWVFeHBvcnRzW2tleV0gPSBwdW55Y29kZVtrZXldKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0Ly8gaW4gUmhpbm8gb3IgYSB3ZWIgYnJvd3NlclxuXHRcdHJvb3QucHVueWNvZGUgPSBwdW55Y29kZTtcblx0fVxuXG59KHRoaXMpKTtcbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4ndXNlIHN0cmljdCc7XG5cbi8vIElmIG9iai5oYXNPd25Qcm9wZXJ0eSBoYXMgYmVlbiBvdmVycmlkZGVuLCB0aGVuIGNhbGxpbmdcbi8vIG9iai5oYXNPd25Qcm9wZXJ0eShwcm9wKSB3aWxsIGJyZWFrLlxuLy8gU2VlOiBodHRwczovL2dpdGh1Yi5jb20vam95ZW50L25vZGUvaXNzdWVzLzE3MDdcbmZ1bmN0aW9uIGhhc093blByb3BlcnR5KG9iaiwgcHJvcCkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24ocXMsIHNlcCwgZXEsIG9wdGlvbnMpIHtcbiAgc2VwID0gc2VwIHx8ICcmJztcbiAgZXEgPSBlcSB8fCAnPSc7XG4gIHZhciBvYmogPSB7fTtcblxuICBpZiAodHlwZW9mIHFzICE9PSAnc3RyaW5nJyB8fCBxcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gb2JqO1xuICB9XG5cbiAgdmFyIHJlZ2V4cCA9IC9cXCsvZztcbiAgcXMgPSBxcy5zcGxpdChzZXApO1xuXG4gIHZhciBtYXhLZXlzID0gMTAwMDtcbiAgaWYgKG9wdGlvbnMgJiYgdHlwZW9mIG9wdGlvbnMubWF4S2V5cyA9PT0gJ251bWJlcicpIHtcbiAgICBtYXhLZXlzID0gb3B0aW9ucy5tYXhLZXlzO1xuICB9XG5cbiAgdmFyIGxlbiA9IHFzLmxlbmd0aDtcbiAgLy8gbWF4S2V5cyA8PSAwIG1lYW5zIHRoYXQgd2Ugc2hvdWxkIG5vdCBsaW1pdCBrZXlzIGNvdW50XG4gIGlmIChtYXhLZXlzID4gMCAmJiBsZW4gPiBtYXhLZXlzKSB7XG4gICAgbGVuID0gbWF4S2V5cztcbiAgfVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICB2YXIgeCA9IHFzW2ldLnJlcGxhY2UocmVnZXhwLCAnJTIwJyksXG4gICAgICAgIGlkeCA9IHguaW5kZXhPZihlcSksXG4gICAgICAgIGtzdHIsIHZzdHIsIGssIHY7XG5cbiAgICBpZiAoaWR4ID49IDApIHtcbiAgICAgIGtzdHIgPSB4LnN1YnN0cigwLCBpZHgpO1xuICAgICAgdnN0ciA9IHguc3Vic3RyKGlkeCArIDEpO1xuICAgIH0gZWxzZSB7XG4gICAgICBrc3RyID0geDtcbiAgICAgIHZzdHIgPSAnJztcbiAgICB9XG5cbiAgICBrID0gZGVjb2RlVVJJQ29tcG9uZW50KGtzdHIpO1xuICAgIHYgPSBkZWNvZGVVUklDb21wb25lbnQodnN0cik7XG5cbiAgICBpZiAoIWhhc093blByb3BlcnR5KG9iaiwgaykpIHtcbiAgICAgIG9ialtrXSA9IHY7XG4gICAgfSBlbHNlIGlmIChpc0FycmF5KG9ialtrXSkpIHtcbiAgICAgIG9ialtrXS5wdXNoKHYpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmpba10gPSBbb2JqW2tdLCB2XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gb2JqO1xufTtcblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uICh4cykge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHhzKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbn07XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgc3RyaW5naWZ5UHJpbWl0aXZlID0gZnVuY3Rpb24odikge1xuICBzd2l0Y2ggKHR5cGVvZiB2KSB7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHJldHVybiB2O1xuXG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4gdiA/ICd0cnVlJyA6ICdmYWxzZSc7XG5cbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgcmV0dXJuIGlzRmluaXRlKHYpID8gdiA6ICcnO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiAnJztcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihvYmosIHNlcCwgZXEsIG5hbWUpIHtcbiAgc2VwID0gc2VwIHx8ICcmJztcbiAgZXEgPSBlcSB8fCAnPSc7XG4gIGlmIChvYmogPT09IG51bGwpIHtcbiAgICBvYmogPSB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gbWFwKG9iamVjdEtleXMob2JqKSwgZnVuY3Rpb24oaykge1xuICAgICAgdmFyIGtzID0gZW5jb2RlVVJJQ29tcG9uZW50KHN0cmluZ2lmeVByaW1pdGl2ZShrKSkgKyBlcTtcbiAgICAgIGlmIChpc0FycmF5KG9ialtrXSkpIHtcbiAgICAgICAgcmV0dXJuIG1hcChvYmpba10sIGZ1bmN0aW9uKHYpIHtcbiAgICAgICAgICByZXR1cm4ga3MgKyBlbmNvZGVVUklDb21wb25lbnQoc3RyaW5naWZ5UHJpbWl0aXZlKHYpKTtcbiAgICAgICAgfSkuam9pbihzZXApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGtzICsgZW5jb2RlVVJJQ29tcG9uZW50KHN0cmluZ2lmeVByaW1pdGl2ZShvYmpba10pKTtcbiAgICAgIH1cbiAgICB9KS5qb2luKHNlcCk7XG5cbiAgfVxuXG4gIGlmICghbmFtZSkgcmV0dXJuICcnO1xuICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KHN0cmluZ2lmeVByaW1pdGl2ZShuYW1lKSkgKyBlcSArXG4gICAgICAgICBlbmNvZGVVUklDb21wb25lbnQoc3RyaW5naWZ5UHJpbWl0aXZlKG9iaikpO1xufTtcblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uICh4cykge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHhzKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbn07XG5cbmZ1bmN0aW9uIG1hcCAoeHMsIGYpIHtcbiAgaWYgKHhzLm1hcCkgcmV0dXJuIHhzLm1hcChmKTtcbiAgdmFyIHJlcyA9IFtdO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHhzLmxlbmd0aDsgaSsrKSB7XG4gICAgcmVzLnB1c2goZih4c1tpXSwgaSkpO1xuICB9XG4gIHJldHVybiByZXM7XG59XG5cbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgZnVuY3Rpb24gKG9iaikge1xuICB2YXIgcmVzID0gW107XG4gIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KSkgcmVzLnB1c2goa2V5KTtcbiAgfVxuICByZXR1cm4gcmVzO1xufTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5kZWNvZGUgPSBleHBvcnRzLnBhcnNlID0gcmVxdWlyZSgnLi9kZWNvZGUnKTtcbmV4cG9ydHMuZW5jb2RlID0gZXhwb3J0cy5zdHJpbmdpZnkgPSByZXF1aXJlKCcuL2VuY29kZScpO1xuIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIGEgZHVwbGV4IHN0cmVhbSBpcyBqdXN0IGEgc3RyZWFtIHRoYXQgaXMgYm90aCByZWFkYWJsZSBhbmQgd3JpdGFibGUuXG4vLyBTaW5jZSBKUyBkb2Vzbid0IGhhdmUgbXVsdGlwbGUgcHJvdG90eXBhbCBpbmhlcml0YW5jZSwgdGhpcyBjbGFzc1xuLy8gcHJvdG90eXBhbGx5IGluaGVyaXRzIGZyb20gUmVhZGFibGUsIGFuZCB0aGVuIHBhcmFzaXRpY2FsbHkgZnJvbVxuLy8gV3JpdGFibGUuXG5cbid1c2Ugc3RyaWN0JztcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cblxudmFyIHBuYSA9IHJlcXVpcmUoJ3Byb2Nlc3MtbmV4dGljay1hcmdzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBvYmplY3RLZXlzID0gT2JqZWN0LmtleXMgfHwgZnVuY3Rpb24gKG9iaikge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAga2V5cy5wdXNoKGtleSk7XG4gIH1yZXR1cm4ga2V5cztcbn07XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxubW9kdWxlLmV4cG9ydHMgPSBEdXBsZXg7XG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgdXRpbCA9IHJlcXVpcmUoJ2NvcmUtdXRpbC1pcycpO1xudXRpbC5pbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxudmFyIFJlYWRhYmxlID0gcmVxdWlyZSgnLi9fc3RyZWFtX3JlYWRhYmxlJyk7XG52YXIgV3JpdGFibGUgPSByZXF1aXJlKCcuL19zdHJlYW1fd3JpdGFibGUnKTtcblxudXRpbC5pbmhlcml0cyhEdXBsZXgsIFJlYWRhYmxlKTtcblxue1xuICAvLyBhdm9pZCBzY29wZSBjcmVlcCwgdGhlIGtleXMgYXJyYXkgY2FuIHRoZW4gYmUgY29sbGVjdGVkXG4gIHZhciBrZXlzID0gb2JqZWN0S2V5cyhXcml0YWJsZS5wcm90b3R5cGUpO1xuICBmb3IgKHZhciB2ID0gMDsgdiA8IGtleXMubGVuZ3RoOyB2KyspIHtcbiAgICB2YXIgbWV0aG9kID0ga2V5c1t2XTtcbiAgICBpZiAoIUR1cGxleC5wcm90b3R5cGVbbWV0aG9kXSkgRHVwbGV4LnByb3RvdHlwZVttZXRob2RdID0gV3JpdGFibGUucHJvdG90eXBlW21ldGhvZF07XG4gIH1cbn1cblxuZnVuY3Rpb24gRHVwbGV4KG9wdGlvbnMpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIER1cGxleCkpIHJldHVybiBuZXcgRHVwbGV4KG9wdGlvbnMpO1xuXG4gIFJlYWRhYmxlLmNhbGwodGhpcywgb3B0aW9ucyk7XG4gIFdyaXRhYmxlLmNhbGwodGhpcywgb3B0aW9ucyk7XG5cbiAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5yZWFkYWJsZSA9PT0gZmFsc2UpIHRoaXMucmVhZGFibGUgPSBmYWxzZTtcblxuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLndyaXRhYmxlID09PSBmYWxzZSkgdGhpcy53cml0YWJsZSA9IGZhbHNlO1xuXG4gIHRoaXMuYWxsb3dIYWxmT3BlbiA9IHRydWU7XG4gIGlmIChvcHRpb25zICYmIG9wdGlvbnMuYWxsb3dIYWxmT3BlbiA9PT0gZmFsc2UpIHRoaXMuYWxsb3dIYWxmT3BlbiA9IGZhbHNlO1xuXG4gIHRoaXMub25jZSgnZW5kJywgb25lbmQpO1xufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoRHVwbGV4LnByb3RvdHlwZSwgJ3dyaXRhYmxlSGlnaFdhdGVyTWFyaycsIHtcbiAgLy8gbWFraW5nIGl0IGV4cGxpY2l0IHRoaXMgcHJvcGVydHkgaXMgbm90IGVudW1lcmFibGVcbiAgLy8gYmVjYXVzZSBvdGhlcndpc2Ugc29tZSBwcm90b3R5cGUgbWFuaXB1bGF0aW9uIGluXG4gIC8vIHVzZXJsYW5kIHdpbGwgZmFpbFxuICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3dyaXRhYmxlU3RhdGUuaGlnaFdhdGVyTWFyaztcbiAgfVxufSk7XG5cbi8vIHRoZSBuby1oYWxmLW9wZW4gZW5mb3JjZXJcbmZ1bmN0aW9uIG9uZW5kKCkge1xuICAvLyBpZiB3ZSBhbGxvdyBoYWxmLW9wZW4gc3RhdGUsIG9yIGlmIHRoZSB3cml0YWJsZSBzaWRlIGVuZGVkLFxuICAvLyB0aGVuIHdlJ3JlIG9rLlxuICBpZiAodGhpcy5hbGxvd0hhbGZPcGVuIHx8IHRoaXMuX3dyaXRhYmxlU3RhdGUuZW5kZWQpIHJldHVybjtcblxuICAvLyBubyBtb3JlIGRhdGEgY2FuIGJlIHdyaXR0ZW4uXG4gIC8vIEJ1dCBhbGxvdyBtb3JlIHdyaXRlcyB0byBoYXBwZW4gaW4gdGhpcyB0aWNrLlxuICBwbmEubmV4dFRpY2sob25FbmROVCwgdGhpcyk7XG59XG5cbmZ1bmN0aW9uIG9uRW5kTlQoc2VsZikge1xuICBzZWxmLmVuZCgpO1xufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoRHVwbGV4LnByb3RvdHlwZSwgJ2Rlc3Ryb3llZCcsIHtcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuX3JlYWRhYmxlU3RhdGUgPT09IHVuZGVmaW5lZCB8fCB0aGlzLl93cml0YWJsZVN0YXRlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGUuZGVzdHJveWVkICYmIHRoaXMuX3dyaXRhYmxlU3RhdGUuZGVzdHJveWVkO1xuICB9LFxuICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIC8vIHdlIGlnbm9yZSB0aGUgdmFsdWUgaWYgdGhlIHN0cmVhbVxuICAgIC8vIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCB5ZXRcbiAgICBpZiAodGhpcy5fcmVhZGFibGVTdGF0ZSA9PT0gdW5kZWZpbmVkIHx8IHRoaXMuX3dyaXRhYmxlU3RhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGJhY2t3YXJkIGNvbXBhdGliaWxpdHksIHRoZSB1c2VyIGlzIGV4cGxpY2l0bHlcbiAgICAvLyBtYW5hZ2luZyBkZXN0cm95ZWRcbiAgICB0aGlzLl9yZWFkYWJsZVN0YXRlLmRlc3Ryb3llZCA9IHZhbHVlO1xuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZGVzdHJveWVkID0gdmFsdWU7XG4gIH1cbn0pO1xuXG5EdXBsZXgucHJvdG90eXBlLl9kZXN0cm95ID0gZnVuY3Rpb24gKGVyciwgY2IpIHtcbiAgdGhpcy5wdXNoKG51bGwpO1xuICB0aGlzLmVuZCgpO1xuXG4gIHBuYS5uZXh0VGljayhjYiwgZXJyKTtcbn07IiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIGEgcGFzc3Rocm91Z2ggc3RyZWFtLlxuLy8gYmFzaWNhbGx5IGp1c3QgdGhlIG1vc3QgbWluaW1hbCBzb3J0IG9mIFRyYW5zZm9ybSBzdHJlYW0uXG4vLyBFdmVyeSB3cml0dGVuIGNodW5rIGdldHMgb3V0cHV0IGFzLWlzLlxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gUGFzc1Rocm91Z2g7XG5cbnZhciBUcmFuc2Zvcm0gPSByZXF1aXJlKCcuL19zdHJlYW1fdHJhbnNmb3JtJyk7XG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgdXRpbCA9IHJlcXVpcmUoJ2NvcmUtdXRpbC1pcycpO1xudXRpbC5pbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxudXRpbC5pbmhlcml0cyhQYXNzVGhyb3VnaCwgVHJhbnNmb3JtKTtcblxuZnVuY3Rpb24gUGFzc1Rocm91Z2gob3B0aW9ucykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUGFzc1Rocm91Z2gpKSByZXR1cm4gbmV3IFBhc3NUaHJvdWdoKG9wdGlvbnMpO1xuXG4gIFRyYW5zZm9ybS5jYWxsKHRoaXMsIG9wdGlvbnMpO1xufVxuXG5QYXNzVGhyb3VnaC5wcm90b3R5cGUuX3RyYW5zZm9ybSA9IGZ1bmN0aW9uIChjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG4gIGNiKG51bGwsIGNodW5rKTtcbn07IiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbid1c2Ugc3RyaWN0JztcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cblxudmFyIHBuYSA9IHJlcXVpcmUoJ3Byb2Nlc3MtbmV4dGljay1hcmdzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxubW9kdWxlLmV4cG9ydHMgPSBSZWFkYWJsZTtcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnaXNhcnJheScpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgRHVwbGV4O1xuLyo8L3JlcGxhY2VtZW50PiovXG5cblJlYWRhYmxlLlJlYWRhYmxlU3RhdGUgPSBSZWFkYWJsZVN0YXRlO1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIEVFID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuXG52YXIgRUVsaXN0ZW5lckNvdW50ID0gZnVuY3Rpb24gKGVtaXR0ZXIsIHR5cGUpIHtcbiAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJzKHR5cGUpLmxlbmd0aDtcbn07XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBTdHJlYW0gPSByZXF1aXJlKCcuL2ludGVybmFsL3N0cmVhbXMvc3RyZWFtJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cblxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyO1xudmFyIE91clVpbnQ4QXJyYXkgPSBnbG9iYWwuVWludDhBcnJheSB8fCBmdW5jdGlvbiAoKSB7fTtcbmZ1bmN0aW9uIF91aW50OEFycmF5VG9CdWZmZXIoY2h1bmspIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGNodW5rKTtcbn1cbmZ1bmN0aW9uIF9pc1VpbnQ4QXJyYXkob2JqKSB7XG4gIHJldHVybiBCdWZmZXIuaXNCdWZmZXIob2JqKSB8fCBvYmogaW5zdGFuY2VvZiBPdXJVaW50OEFycmF5O1xufVxuXG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciB1dGlsID0gcmVxdWlyZSgnY29yZS11dGlsLWlzJyk7XG51dGlsLmluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKTtcbi8qPC9yZXBsYWNlbWVudD4qL1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIGRlYnVnVXRpbCA9IHJlcXVpcmUoJ3V0aWwnKTtcbnZhciBkZWJ1ZyA9IHZvaWQgMDtcbmlmIChkZWJ1Z1V0aWwgJiYgZGVidWdVdGlsLmRlYnVnbG9nKSB7XG4gIGRlYnVnID0gZGVidWdVdGlsLmRlYnVnbG9nKCdzdHJlYW0nKTtcbn0gZWxzZSB7XG4gIGRlYnVnID0gZnVuY3Rpb24gKCkge307XG59XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxudmFyIEJ1ZmZlckxpc3QgPSByZXF1aXJlKCcuL2ludGVybmFsL3N0cmVhbXMvQnVmZmVyTGlzdCcpO1xudmFyIGRlc3Ryb3lJbXBsID0gcmVxdWlyZSgnLi9pbnRlcm5hbC9zdHJlYW1zL2Rlc3Ryb3knKTtcbnZhciBTdHJpbmdEZWNvZGVyO1xuXG51dGlsLmluaGVyaXRzKFJlYWRhYmxlLCBTdHJlYW0pO1xuXG52YXIga1Byb3h5RXZlbnRzID0gWydlcnJvcicsICdjbG9zZScsICdkZXN0cm95JywgJ3BhdXNlJywgJ3Jlc3VtZSddO1xuXG5mdW5jdGlvbiBwcmVwZW5kTGlzdGVuZXIoZW1pdHRlciwgZXZlbnQsIGZuKSB7XG4gIC8vIFNhZGx5IHRoaXMgaXMgbm90IGNhY2hlYWJsZSBhcyBzb21lIGxpYnJhcmllcyBidW5kbGUgdGhlaXIgb3duXG4gIC8vIGV2ZW50IGVtaXR0ZXIgaW1wbGVtZW50YXRpb24gd2l0aCB0aGVtLlxuICBpZiAodHlwZW9mIGVtaXR0ZXIucHJlcGVuZExpc3RlbmVyID09PSAnZnVuY3Rpb24nKSByZXR1cm4gZW1pdHRlci5wcmVwZW5kTGlzdGVuZXIoZXZlbnQsIGZuKTtcblxuICAvLyBUaGlzIGlzIGEgaGFjayB0byBtYWtlIHN1cmUgdGhhdCBvdXIgZXJyb3IgaGFuZGxlciBpcyBhdHRhY2hlZCBiZWZvcmUgYW55XG4gIC8vIHVzZXJsYW5kIG9uZXMuICBORVZFUiBETyBUSElTLiBUaGlzIGlzIGhlcmUgb25seSBiZWNhdXNlIHRoaXMgY29kZSBuZWVkc1xuICAvLyB0byBjb250aW51ZSB0byB3b3JrIHdpdGggb2xkZXIgdmVyc2lvbnMgb2YgTm9kZS5qcyB0aGF0IGRvIG5vdCBpbmNsdWRlXG4gIC8vIHRoZSBwcmVwZW5kTGlzdGVuZXIoKSBtZXRob2QuIFRoZSBnb2FsIGlzIHRvIGV2ZW50dWFsbHkgcmVtb3ZlIHRoaXMgaGFjay5cbiAgaWYgKCFlbWl0dGVyLl9ldmVudHMgfHwgIWVtaXR0ZXIuX2V2ZW50c1tldmVudF0pIGVtaXR0ZXIub24oZXZlbnQsIGZuKTtlbHNlIGlmIChpc0FycmF5KGVtaXR0ZXIuX2V2ZW50c1tldmVudF0pKSBlbWl0dGVyLl9ldmVudHNbZXZlbnRdLnVuc2hpZnQoZm4pO2Vsc2UgZW1pdHRlci5fZXZlbnRzW2V2ZW50XSA9IFtmbiwgZW1pdHRlci5fZXZlbnRzW2V2ZW50XV07XG59XG5cbmZ1bmN0aW9uIFJlYWRhYmxlU3RhdGUob3B0aW9ucywgc3RyZWFtKSB7XG4gIER1cGxleCA9IER1cGxleCB8fCByZXF1aXJlKCcuL19zdHJlYW1fZHVwbGV4Jyk7XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgLy8gRHVwbGV4IHN0cmVhbXMgYXJlIGJvdGggcmVhZGFibGUgYW5kIHdyaXRhYmxlLCBidXQgc2hhcmVcbiAgLy8gdGhlIHNhbWUgb3B0aW9ucyBvYmplY3QuXG4gIC8vIEhvd2V2ZXIsIHNvbWUgY2FzZXMgcmVxdWlyZSBzZXR0aW5nIG9wdGlvbnMgdG8gZGlmZmVyZW50XG4gIC8vIHZhbHVlcyBmb3IgdGhlIHJlYWRhYmxlIGFuZCB0aGUgd3JpdGFibGUgc2lkZXMgb2YgdGhlIGR1cGxleCBzdHJlYW0uXG4gIC8vIFRoZXNlIG9wdGlvbnMgY2FuIGJlIHByb3ZpZGVkIHNlcGFyYXRlbHkgYXMgcmVhZGFibGVYWFggYW5kIHdyaXRhYmxlWFhYLlxuICB2YXIgaXNEdXBsZXggPSBzdHJlYW0gaW5zdGFuY2VvZiBEdXBsZXg7XG5cbiAgLy8gb2JqZWN0IHN0cmVhbSBmbGFnLiBVc2VkIHRvIG1ha2UgcmVhZChuKSBpZ25vcmUgbiBhbmQgdG9cbiAgLy8gbWFrZSBhbGwgdGhlIGJ1ZmZlciBtZXJnaW5nIGFuZCBsZW5ndGggY2hlY2tzIGdvIGF3YXlcbiAgdGhpcy5vYmplY3RNb2RlID0gISFvcHRpb25zLm9iamVjdE1vZGU7XG5cbiAgaWYgKGlzRHVwbGV4KSB0aGlzLm9iamVjdE1vZGUgPSB0aGlzLm9iamVjdE1vZGUgfHwgISFvcHRpb25zLnJlYWRhYmxlT2JqZWN0TW9kZTtcblxuICAvLyB0aGUgcG9pbnQgYXQgd2hpY2ggaXQgc3RvcHMgY2FsbGluZyBfcmVhZCgpIHRvIGZpbGwgdGhlIGJ1ZmZlclxuICAvLyBOb3RlOiAwIGlzIGEgdmFsaWQgdmFsdWUsIG1lYW5zIFwiZG9uJ3QgY2FsbCBfcmVhZCBwcmVlbXB0aXZlbHkgZXZlclwiXG4gIHZhciBod20gPSBvcHRpb25zLmhpZ2hXYXRlck1hcms7XG4gIHZhciByZWFkYWJsZUh3bSA9IG9wdGlvbnMucmVhZGFibGVIaWdoV2F0ZXJNYXJrO1xuICB2YXIgZGVmYXVsdEh3bSA9IHRoaXMub2JqZWN0TW9kZSA/IDE2IDogMTYgKiAxMDI0O1xuXG4gIGlmIChod20gfHwgaHdtID09PSAwKSB0aGlzLmhpZ2hXYXRlck1hcmsgPSBod207ZWxzZSBpZiAoaXNEdXBsZXggJiYgKHJlYWRhYmxlSHdtIHx8IHJlYWRhYmxlSHdtID09PSAwKSkgdGhpcy5oaWdoV2F0ZXJNYXJrID0gcmVhZGFibGVId207ZWxzZSB0aGlzLmhpZ2hXYXRlck1hcmsgPSBkZWZhdWx0SHdtO1xuXG4gIC8vIGNhc3QgdG8gaW50cy5cbiAgdGhpcy5oaWdoV2F0ZXJNYXJrID0gTWF0aC5mbG9vcih0aGlzLmhpZ2hXYXRlck1hcmspO1xuXG4gIC8vIEEgbGlua2VkIGxpc3QgaXMgdXNlZCB0byBzdG9yZSBkYXRhIGNodW5rcyBpbnN0ZWFkIG9mIGFuIGFycmF5IGJlY2F1c2UgdGhlXG4gIC8vIGxpbmtlZCBsaXN0IGNhbiByZW1vdmUgZWxlbWVudHMgZnJvbSB0aGUgYmVnaW5uaW5nIGZhc3RlciB0aGFuXG4gIC8vIGFycmF5LnNoaWZ0KClcbiAgdGhpcy5idWZmZXIgPSBuZXcgQnVmZmVyTGlzdCgpO1xuICB0aGlzLmxlbmd0aCA9IDA7XG4gIHRoaXMucGlwZXMgPSBudWxsO1xuICB0aGlzLnBpcGVzQ291bnQgPSAwO1xuICB0aGlzLmZsb3dpbmcgPSBudWxsO1xuICB0aGlzLmVuZGVkID0gZmFsc2U7XG4gIHRoaXMuZW5kRW1pdHRlZCA9IGZhbHNlO1xuICB0aGlzLnJlYWRpbmcgPSBmYWxzZTtcblxuICAvLyBhIGZsYWcgdG8gYmUgYWJsZSB0byB0ZWxsIGlmIHRoZSBldmVudCAncmVhZGFibGUnLydkYXRhJyBpcyBlbWl0dGVkXG4gIC8vIGltbWVkaWF0ZWx5LCBvciBvbiBhIGxhdGVyIHRpY2suICBXZSBzZXQgdGhpcyB0byB0cnVlIGF0IGZpcnN0LCBiZWNhdXNlXG4gIC8vIGFueSBhY3Rpb25zIHRoYXQgc2hvdWxkbid0IGhhcHBlbiB1bnRpbCBcImxhdGVyXCIgc2hvdWxkIGdlbmVyYWxseSBhbHNvXG4gIC8vIG5vdCBoYXBwZW4gYmVmb3JlIHRoZSBmaXJzdCByZWFkIGNhbGwuXG4gIHRoaXMuc3luYyA9IHRydWU7XG5cbiAgLy8gd2hlbmV2ZXIgd2UgcmV0dXJuIG51bGwsIHRoZW4gd2Ugc2V0IGEgZmxhZyB0byBzYXlcbiAgLy8gdGhhdCB3ZSdyZSBhd2FpdGluZyBhICdyZWFkYWJsZScgZXZlbnQgZW1pc3Npb24uXG4gIHRoaXMubmVlZFJlYWRhYmxlID0gZmFsc2U7XG4gIHRoaXMuZW1pdHRlZFJlYWRhYmxlID0gZmFsc2U7XG4gIHRoaXMucmVhZGFibGVMaXN0ZW5pbmcgPSBmYWxzZTtcbiAgdGhpcy5yZXN1bWVTY2hlZHVsZWQgPSBmYWxzZTtcblxuICAvLyBoYXMgaXQgYmVlbiBkZXN0cm95ZWRcbiAgdGhpcy5kZXN0cm95ZWQgPSBmYWxzZTtcblxuICAvLyBDcnlwdG8gaXMga2luZCBvZiBvbGQgYW5kIGNydXN0eS4gIEhpc3RvcmljYWxseSwgaXRzIGRlZmF1bHQgc3RyaW5nXG4gIC8vIGVuY29kaW5nIGlzICdiaW5hcnknIHNvIHdlIGhhdmUgdG8gbWFrZSB0aGlzIGNvbmZpZ3VyYWJsZS5cbiAgLy8gRXZlcnl0aGluZyBlbHNlIGluIHRoZSB1bml2ZXJzZSB1c2VzICd1dGY4JywgdGhvdWdoLlxuICB0aGlzLmRlZmF1bHRFbmNvZGluZyA9IG9wdGlvbnMuZGVmYXVsdEVuY29kaW5nIHx8ICd1dGY4JztcblxuICAvLyB0aGUgbnVtYmVyIG9mIHdyaXRlcnMgdGhhdCBhcmUgYXdhaXRpbmcgYSBkcmFpbiBldmVudCBpbiAucGlwZSgpc1xuICB0aGlzLmF3YWl0RHJhaW4gPSAwO1xuXG4gIC8vIGlmIHRydWUsIGEgbWF5YmVSZWFkTW9yZSBoYXMgYmVlbiBzY2hlZHVsZWRcbiAgdGhpcy5yZWFkaW5nTW9yZSA9IGZhbHNlO1xuXG4gIHRoaXMuZGVjb2RlciA9IG51bGw7XG4gIHRoaXMuZW5jb2RpbmcgPSBudWxsO1xuICBpZiAob3B0aW9ucy5lbmNvZGluZykge1xuICAgIGlmICghU3RyaW5nRGVjb2RlcikgU3RyaW5nRGVjb2RlciA9IHJlcXVpcmUoJ3N0cmluZ19kZWNvZGVyLycpLlN0cmluZ0RlY29kZXI7XG4gICAgdGhpcy5kZWNvZGVyID0gbmV3IFN0cmluZ0RlY29kZXIob3B0aW9ucy5lbmNvZGluZyk7XG4gICAgdGhpcy5lbmNvZGluZyA9IG9wdGlvbnMuZW5jb2Rpbmc7XG4gIH1cbn1cblxuZnVuY3Rpb24gUmVhZGFibGUob3B0aW9ucykge1xuICBEdXBsZXggPSBEdXBsZXggfHwgcmVxdWlyZSgnLi9fc3RyZWFtX2R1cGxleCcpO1xuXG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSZWFkYWJsZSkpIHJldHVybiBuZXcgUmVhZGFibGUob3B0aW9ucyk7XG5cbiAgdGhpcy5fcmVhZGFibGVTdGF0ZSA9IG5ldyBSZWFkYWJsZVN0YXRlKG9wdGlvbnMsIHRoaXMpO1xuXG4gIC8vIGxlZ2FjeVxuICB0aGlzLnJlYWRhYmxlID0gdHJ1ZTtcblxuICBpZiAob3B0aW9ucykge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yZWFkID09PSAnZnVuY3Rpb24nKSB0aGlzLl9yZWFkID0gb3B0aW9ucy5yZWFkO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmRlc3Ryb3kgPT09ICdmdW5jdGlvbicpIHRoaXMuX2Rlc3Ryb3kgPSBvcHRpb25zLmRlc3Ryb3k7XG4gIH1cblxuICBTdHJlYW0uY2FsbCh0aGlzKTtcbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlYWRhYmxlLnByb3RvdHlwZSwgJ2Rlc3Ryb3llZCcsIHtcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuX3JlYWRhYmxlU3RhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fcmVhZGFibGVTdGF0ZS5kZXN0cm95ZWQ7XG4gIH0sXG4gIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgLy8gd2UgaWdub3JlIHRoZSB2YWx1ZSBpZiB0aGUgc3RyZWFtXG4gICAgLy8gaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkIHlldFxuICAgIGlmICghdGhpcy5fcmVhZGFibGVTdGF0ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGJhY2t3YXJkIGNvbXBhdGliaWxpdHksIHRoZSB1c2VyIGlzIGV4cGxpY2l0bHlcbiAgICAvLyBtYW5hZ2luZyBkZXN0cm95ZWRcbiAgICB0aGlzLl9yZWFkYWJsZVN0YXRlLmRlc3Ryb3llZCA9IHZhbHVlO1xuICB9XG59KTtcblxuUmVhZGFibGUucHJvdG90eXBlLmRlc3Ryb3kgPSBkZXN0cm95SW1wbC5kZXN0cm95O1xuUmVhZGFibGUucHJvdG90eXBlLl91bmRlc3Ryb3kgPSBkZXN0cm95SW1wbC51bmRlc3Ryb3k7XG5SZWFkYWJsZS5wcm90b3R5cGUuX2Rlc3Ryb3kgPSBmdW5jdGlvbiAoZXJyLCBjYikge1xuICB0aGlzLnB1c2gobnVsbCk7XG4gIGNiKGVycik7XG59O1xuXG4vLyBNYW51YWxseSBzaG92ZSBzb21ldGhpbmcgaW50byB0aGUgcmVhZCgpIGJ1ZmZlci5cbi8vIFRoaXMgcmV0dXJucyB0cnVlIGlmIHRoZSBoaWdoV2F0ZXJNYXJrIGhhcyBub3QgYmVlbiBoaXQgeWV0LFxuLy8gc2ltaWxhciB0byBob3cgV3JpdGFibGUud3JpdGUoKSByZXR1cm5zIHRydWUgaWYgeW91IHNob3VsZFxuLy8gd3JpdGUoKSBzb21lIG1vcmUuXG5SZWFkYWJsZS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uIChjaHVuaywgZW5jb2RpbmcpIHtcbiAgdmFyIHN0YXRlID0gdGhpcy5fcmVhZGFibGVTdGF0ZTtcbiAgdmFyIHNraXBDaHVua0NoZWNrO1xuXG4gIGlmICghc3RhdGUub2JqZWN0TW9kZSkge1xuICAgIGlmICh0eXBlb2YgY2h1bmsgPT09ICdzdHJpbmcnKSB7XG4gICAgICBlbmNvZGluZyA9IGVuY29kaW5nIHx8IHN0YXRlLmRlZmF1bHRFbmNvZGluZztcbiAgICAgIGlmIChlbmNvZGluZyAhPT0gc3RhdGUuZW5jb2RpbmcpIHtcbiAgICAgICAgY2h1bmsgPSBCdWZmZXIuZnJvbShjaHVuaywgZW5jb2RpbmcpO1xuICAgICAgICBlbmNvZGluZyA9ICcnO1xuICAgICAgfVxuICAgICAgc2tpcENodW5rQ2hlY2sgPSB0cnVlO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBza2lwQ2h1bmtDaGVjayA9IHRydWU7XG4gIH1cblxuICByZXR1cm4gcmVhZGFibGVBZGRDaHVuayh0aGlzLCBjaHVuaywgZW5jb2RpbmcsIGZhbHNlLCBza2lwQ2h1bmtDaGVjayk7XG59O1xuXG4vLyBVbnNoaWZ0IHNob3VsZCAqYWx3YXlzKiBiZSBzb21ldGhpbmcgZGlyZWN0bHkgb3V0IG9mIHJlYWQoKVxuUmVhZGFibGUucHJvdG90eXBlLnVuc2hpZnQgPSBmdW5jdGlvbiAoY2h1bmspIHtcbiAgcmV0dXJuIHJlYWRhYmxlQWRkQ2h1bmsodGhpcywgY2h1bmssIG51bGwsIHRydWUsIGZhbHNlKTtcbn07XG5cbmZ1bmN0aW9uIHJlYWRhYmxlQWRkQ2h1bmsoc3RyZWFtLCBjaHVuaywgZW5jb2RpbmcsIGFkZFRvRnJvbnQsIHNraXBDaHVua0NoZWNrKSB7XG4gIHZhciBzdGF0ZSA9IHN0cmVhbS5fcmVhZGFibGVTdGF0ZTtcbiAgaWYgKGNodW5rID09PSBudWxsKSB7XG4gICAgc3RhdGUucmVhZGluZyA9IGZhbHNlO1xuICAgIG9uRW9mQ2h1bmsoc3RyZWFtLCBzdGF0ZSk7XG4gIH0gZWxzZSB7XG4gICAgdmFyIGVyO1xuICAgIGlmICghc2tpcENodW5rQ2hlY2spIGVyID0gY2h1bmtJbnZhbGlkKHN0YXRlLCBjaHVuayk7XG4gICAgaWYgKGVyKSB7XG4gICAgICBzdHJlYW0uZW1pdCgnZXJyb3InLCBlcik7XG4gICAgfSBlbHNlIGlmIChzdGF0ZS5vYmplY3RNb2RlIHx8IGNodW5rICYmIGNodW5rLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmICh0eXBlb2YgY2h1bmsgIT09ICdzdHJpbmcnICYmICFzdGF0ZS5vYmplY3RNb2RlICYmIE9iamVjdC5nZXRQcm90b3R5cGVPZihjaHVuaykgIT09IEJ1ZmZlci5wcm90b3R5cGUpIHtcbiAgICAgICAgY2h1bmsgPSBfdWludDhBcnJheVRvQnVmZmVyKGNodW5rKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFkZFRvRnJvbnQpIHtcbiAgICAgICAgaWYgKHN0YXRlLmVuZEVtaXR0ZWQpIHN0cmVhbS5lbWl0KCdlcnJvcicsIG5ldyBFcnJvcignc3RyZWFtLnVuc2hpZnQoKSBhZnRlciBlbmQgZXZlbnQnKSk7ZWxzZSBhZGRDaHVuayhzdHJlYW0sIHN0YXRlLCBjaHVuaywgdHJ1ZSk7XG4gICAgICB9IGVsc2UgaWYgKHN0YXRlLmVuZGVkKSB7XG4gICAgICAgIHN0cmVhbS5lbWl0KCdlcnJvcicsIG5ldyBFcnJvcignc3RyZWFtLnB1c2goKSBhZnRlciBFT0YnKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdGF0ZS5yZWFkaW5nID0gZmFsc2U7XG4gICAgICAgIGlmIChzdGF0ZS5kZWNvZGVyICYmICFlbmNvZGluZykge1xuICAgICAgICAgIGNodW5rID0gc3RhdGUuZGVjb2Rlci53cml0ZShjaHVuayk7XG4gICAgICAgICAgaWYgKHN0YXRlLm9iamVjdE1vZGUgfHwgY2h1bmsubGVuZ3RoICE9PSAwKSBhZGRDaHVuayhzdHJlYW0sIHN0YXRlLCBjaHVuaywgZmFsc2UpO2Vsc2UgbWF5YmVSZWFkTW9yZShzdHJlYW0sIHN0YXRlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhZGRDaHVuayhzdHJlYW0sIHN0YXRlLCBjaHVuaywgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICghYWRkVG9Gcm9udCkge1xuICAgICAgc3RhdGUucmVhZGluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZWVkTW9yZURhdGEoc3RhdGUpO1xufVxuXG5mdW5jdGlvbiBhZGRDaHVuayhzdHJlYW0sIHN0YXRlLCBjaHVuaywgYWRkVG9Gcm9udCkge1xuICBpZiAoc3RhdGUuZmxvd2luZyAmJiBzdGF0ZS5sZW5ndGggPT09IDAgJiYgIXN0YXRlLnN5bmMpIHtcbiAgICBzdHJlYW0uZW1pdCgnZGF0YScsIGNodW5rKTtcbiAgICBzdHJlYW0ucmVhZCgwKTtcbiAgfSBlbHNlIHtcbiAgICAvLyB1cGRhdGUgdGhlIGJ1ZmZlciBpbmZvLlxuICAgIHN0YXRlLmxlbmd0aCArPSBzdGF0ZS5vYmplY3RNb2RlID8gMSA6IGNodW5rLmxlbmd0aDtcbiAgICBpZiAoYWRkVG9Gcm9udCkgc3RhdGUuYnVmZmVyLnVuc2hpZnQoY2h1bmspO2Vsc2Ugc3RhdGUuYnVmZmVyLnB1c2goY2h1bmspO1xuXG4gICAgaWYgKHN0YXRlLm5lZWRSZWFkYWJsZSkgZW1pdFJlYWRhYmxlKHN0cmVhbSk7XG4gIH1cbiAgbWF5YmVSZWFkTW9yZShzdHJlYW0sIHN0YXRlKTtcbn1cblxuZnVuY3Rpb24gY2h1bmtJbnZhbGlkKHN0YXRlLCBjaHVuaykge1xuICB2YXIgZXI7XG4gIGlmICghX2lzVWludDhBcnJheShjaHVuaykgJiYgdHlwZW9mIGNodW5rICE9PSAnc3RyaW5nJyAmJiBjaHVuayAhPT0gdW5kZWZpbmVkICYmICFzdGF0ZS5vYmplY3RNb2RlKSB7XG4gICAgZXIgPSBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIG5vbi1zdHJpbmcvYnVmZmVyIGNodW5rJyk7XG4gIH1cbiAgcmV0dXJuIGVyO1xufVxuXG4vLyBpZiBpdCdzIHBhc3QgdGhlIGhpZ2ggd2F0ZXIgbWFyaywgd2UgY2FuIHB1c2ggaW4gc29tZSBtb3JlLlxuLy8gQWxzbywgaWYgd2UgaGF2ZSBubyBkYXRhIHlldCwgd2UgY2FuIHN0YW5kIHNvbWVcbi8vIG1vcmUgYnl0ZXMuICBUaGlzIGlzIHRvIHdvcmsgYXJvdW5kIGNhc2VzIHdoZXJlIGh3bT0wLFxuLy8gc3VjaCBhcyB0aGUgcmVwbC4gIEFsc28sIGlmIHRoZSBwdXNoKCkgdHJpZ2dlcmVkIGFcbi8vIHJlYWRhYmxlIGV2ZW50LCBhbmQgdGhlIHVzZXIgY2FsbGVkIHJlYWQobGFyZ2VOdW1iZXIpIHN1Y2ggdGhhdFxuLy8gbmVlZFJlYWRhYmxlIHdhcyBzZXQsIHRoZW4gd2Ugb3VnaHQgdG8gcHVzaCBtb3JlLCBzbyB0aGF0IGFub3RoZXJcbi8vICdyZWFkYWJsZScgZXZlbnQgd2lsbCBiZSB0cmlnZ2VyZWQuXG5mdW5jdGlvbiBuZWVkTW9yZURhdGEoc3RhdGUpIHtcbiAgcmV0dXJuICFzdGF0ZS5lbmRlZCAmJiAoc3RhdGUubmVlZFJlYWRhYmxlIHx8IHN0YXRlLmxlbmd0aCA8IHN0YXRlLmhpZ2hXYXRlck1hcmsgfHwgc3RhdGUubGVuZ3RoID09PSAwKTtcbn1cblxuUmVhZGFibGUucHJvdG90eXBlLmlzUGF1c2VkID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nID09PSBmYWxzZTtcbn07XG5cbi8vIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxuUmVhZGFibGUucHJvdG90eXBlLnNldEVuY29kaW5nID0gZnVuY3Rpb24gKGVuYykge1xuICBpZiAoIVN0cmluZ0RlY29kZXIpIFN0cmluZ0RlY29kZXIgPSByZXF1aXJlKCdzdHJpbmdfZGVjb2Rlci8nKS5TdHJpbmdEZWNvZGVyO1xuICB0aGlzLl9yZWFkYWJsZVN0YXRlLmRlY29kZXIgPSBuZXcgU3RyaW5nRGVjb2RlcihlbmMpO1xuICB0aGlzLl9yZWFkYWJsZVN0YXRlLmVuY29kaW5nID0gZW5jO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIERvbid0IHJhaXNlIHRoZSBod20gPiA4TUJcbnZhciBNQVhfSFdNID0gMHg4MDAwMDA7XG5mdW5jdGlvbiBjb21wdXRlTmV3SGlnaFdhdGVyTWFyayhuKSB7XG4gIGlmIChuID49IE1BWF9IV00pIHtcbiAgICBuID0gTUFYX0hXTTtcbiAgfSBlbHNlIHtcbiAgICAvLyBHZXQgdGhlIG5leHQgaGlnaGVzdCBwb3dlciBvZiAyIHRvIHByZXZlbnQgaW5jcmVhc2luZyBod20gZXhjZXNzaXZlbHkgaW5cbiAgICAvLyB0aW55IGFtb3VudHNcbiAgICBuLS07XG4gICAgbiB8PSBuID4+PiAxO1xuICAgIG4gfD0gbiA+Pj4gMjtcbiAgICBuIHw9IG4gPj4+IDQ7XG4gICAgbiB8PSBuID4+PiA4O1xuICAgIG4gfD0gbiA+Pj4gMTY7XG4gICAgbisrO1xuICB9XG4gIHJldHVybiBuO1xufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGlzIGRlc2lnbmVkIHRvIGJlIGlubGluYWJsZSwgc28gcGxlYXNlIHRha2UgY2FyZSB3aGVuIG1ha2luZ1xuLy8gY2hhbmdlcyB0byB0aGUgZnVuY3Rpb24gYm9keS5cbmZ1bmN0aW9uIGhvd011Y2hUb1JlYWQobiwgc3RhdGUpIHtcbiAgaWYgKG4gPD0gMCB8fCBzdGF0ZS5sZW5ndGggPT09IDAgJiYgc3RhdGUuZW5kZWQpIHJldHVybiAwO1xuICBpZiAoc3RhdGUub2JqZWN0TW9kZSkgcmV0dXJuIDE7XG4gIGlmIChuICE9PSBuKSB7XG4gICAgLy8gT25seSBmbG93IG9uZSBidWZmZXIgYXQgYSB0aW1lXG4gICAgaWYgKHN0YXRlLmZsb3dpbmcgJiYgc3RhdGUubGVuZ3RoKSByZXR1cm4gc3RhdGUuYnVmZmVyLmhlYWQuZGF0YS5sZW5ndGg7ZWxzZSByZXR1cm4gc3RhdGUubGVuZ3RoO1xuICB9XG4gIC8vIElmIHdlJ3JlIGFza2luZyBmb3IgbW9yZSB0aGFuIHRoZSBjdXJyZW50IGh3bSwgdGhlbiByYWlzZSB0aGUgaHdtLlxuICBpZiAobiA+IHN0YXRlLmhpZ2hXYXRlck1hcmspIHN0YXRlLmhpZ2hXYXRlck1hcmsgPSBjb21wdXRlTmV3SGlnaFdhdGVyTWFyayhuKTtcbiAgaWYgKG4gPD0gc3RhdGUubGVuZ3RoKSByZXR1cm4gbjtcbiAgLy8gRG9uJ3QgaGF2ZSBlbm91Z2hcbiAgaWYgKCFzdGF0ZS5lbmRlZCkge1xuICAgIHN0YXRlLm5lZWRSZWFkYWJsZSA9IHRydWU7XG4gICAgcmV0dXJuIDA7XG4gIH1cbiAgcmV0dXJuIHN0YXRlLmxlbmd0aDtcbn1cblxuLy8geW91IGNhbiBvdmVycmlkZSBlaXRoZXIgdGhpcyBtZXRob2QsIG9yIHRoZSBhc3luYyBfcmVhZChuKSBiZWxvdy5cblJlYWRhYmxlLnByb3RvdHlwZS5yZWFkID0gZnVuY3Rpb24gKG4pIHtcbiAgZGVidWcoJ3JlYWQnLCBuKTtcbiAgbiA9IHBhcnNlSW50KG4sIDEwKTtcbiAgdmFyIHN0YXRlID0gdGhpcy5fcmVhZGFibGVTdGF0ZTtcbiAgdmFyIG5PcmlnID0gbjtcblxuICBpZiAobiAhPT0gMCkgc3RhdGUuZW1pdHRlZFJlYWRhYmxlID0gZmFsc2U7XG5cbiAgLy8gaWYgd2UncmUgZG9pbmcgcmVhZCgwKSB0byB0cmlnZ2VyIGEgcmVhZGFibGUgZXZlbnQsIGJ1dCB3ZVxuICAvLyBhbHJlYWR5IGhhdmUgYSBidW5jaCBvZiBkYXRhIGluIHRoZSBidWZmZXIsIHRoZW4ganVzdCB0cmlnZ2VyXG4gIC8vIHRoZSAncmVhZGFibGUnIGV2ZW50IGFuZCBtb3ZlIG9uLlxuICBpZiAobiA9PT0gMCAmJiBzdGF0ZS5uZWVkUmVhZGFibGUgJiYgKHN0YXRlLmxlbmd0aCA+PSBzdGF0ZS5oaWdoV2F0ZXJNYXJrIHx8IHN0YXRlLmVuZGVkKSkge1xuICAgIGRlYnVnKCdyZWFkOiBlbWl0UmVhZGFibGUnLCBzdGF0ZS5sZW5ndGgsIHN0YXRlLmVuZGVkKTtcbiAgICBpZiAoc3RhdGUubGVuZ3RoID09PSAwICYmIHN0YXRlLmVuZGVkKSBlbmRSZWFkYWJsZSh0aGlzKTtlbHNlIGVtaXRSZWFkYWJsZSh0aGlzKTtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIG4gPSBob3dNdWNoVG9SZWFkKG4sIHN0YXRlKTtcblxuICAvLyBpZiB3ZSd2ZSBlbmRlZCwgYW5kIHdlJ3JlIG5vdyBjbGVhciwgdGhlbiBmaW5pc2ggaXQgdXAuXG4gIGlmIChuID09PSAwICYmIHN0YXRlLmVuZGVkKSB7XG4gICAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCkgZW5kUmVhZGFibGUodGhpcyk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICAvLyBBbGwgdGhlIGFjdHVhbCBjaHVuayBnZW5lcmF0aW9uIGxvZ2ljIG5lZWRzIHRvIGJlXG4gIC8vICpiZWxvdyogdGhlIGNhbGwgdG8gX3JlYWQuICBUaGUgcmVhc29uIGlzIHRoYXQgaW4gY2VydGFpblxuICAvLyBzeW50aGV0aWMgc3RyZWFtIGNhc2VzLCBzdWNoIGFzIHBhc3N0aHJvdWdoIHN0cmVhbXMsIF9yZWFkXG4gIC8vIG1heSBiZSBhIGNvbXBsZXRlbHkgc3luY2hyb25vdXMgb3BlcmF0aW9uIHdoaWNoIG1heSBjaGFuZ2VcbiAgLy8gdGhlIHN0YXRlIG9mIHRoZSByZWFkIGJ1ZmZlciwgcHJvdmlkaW5nIGVub3VnaCBkYXRhIHdoZW5cbiAgLy8gYmVmb3JlIHRoZXJlIHdhcyAqbm90KiBlbm91Z2guXG4gIC8vXG4gIC8vIFNvLCB0aGUgc3RlcHMgYXJlOlxuICAvLyAxLiBGaWd1cmUgb3V0IHdoYXQgdGhlIHN0YXRlIG9mIHRoaW5ncyB3aWxsIGJlIGFmdGVyIHdlIGRvXG4gIC8vIGEgcmVhZCBmcm9tIHRoZSBidWZmZXIuXG4gIC8vXG4gIC8vIDIuIElmIHRoYXQgcmVzdWx0aW5nIHN0YXRlIHdpbGwgdHJpZ2dlciBhIF9yZWFkLCB0aGVuIGNhbGwgX3JlYWQuXG4gIC8vIE5vdGUgdGhhdCB0aGlzIG1heSBiZSBhc3luY2hyb25vdXMsIG9yIHN5bmNocm9ub3VzLiAgWWVzLCBpdCBpc1xuICAvLyBkZWVwbHkgdWdseSB0byB3cml0ZSBBUElzIHRoaXMgd2F5LCBidXQgdGhhdCBzdGlsbCBkb2Vzbid0IG1lYW5cbiAgLy8gdGhhdCB0aGUgUmVhZGFibGUgY2xhc3Mgc2hvdWxkIGJlaGF2ZSBpbXByb3Blcmx5LCBhcyBzdHJlYW1zIGFyZVxuICAvLyBkZXNpZ25lZCB0byBiZSBzeW5jL2FzeW5jIGFnbm9zdGljLlxuICAvLyBUYWtlIG5vdGUgaWYgdGhlIF9yZWFkIGNhbGwgaXMgc3luYyBvciBhc3luYyAoaWUsIGlmIHRoZSByZWFkIGNhbGxcbiAgLy8gaGFzIHJldHVybmVkIHlldCksIHNvIHRoYXQgd2Uga25vdyB3aGV0aGVyIG9yIG5vdCBpdCdzIHNhZmUgdG8gZW1pdFxuICAvLyAncmVhZGFibGUnIGV0Yy5cbiAgLy9cbiAgLy8gMy4gQWN0dWFsbHkgcHVsbCB0aGUgcmVxdWVzdGVkIGNodW5rcyBvdXQgb2YgdGhlIGJ1ZmZlciBhbmQgcmV0dXJuLlxuXG4gIC8vIGlmIHdlIG5lZWQgYSByZWFkYWJsZSBldmVudCwgdGhlbiB3ZSBuZWVkIHRvIGRvIHNvbWUgcmVhZGluZy5cbiAgdmFyIGRvUmVhZCA9IHN0YXRlLm5lZWRSZWFkYWJsZTtcbiAgZGVidWcoJ25lZWQgcmVhZGFibGUnLCBkb1JlYWQpO1xuXG4gIC8vIGlmIHdlIGN1cnJlbnRseSBoYXZlIGxlc3MgdGhhbiB0aGUgaGlnaFdhdGVyTWFyaywgdGhlbiBhbHNvIHJlYWQgc29tZVxuICBpZiAoc3RhdGUubGVuZ3RoID09PSAwIHx8IHN0YXRlLmxlbmd0aCAtIG4gPCBzdGF0ZS5oaWdoV2F0ZXJNYXJrKSB7XG4gICAgZG9SZWFkID0gdHJ1ZTtcbiAgICBkZWJ1ZygnbGVuZ3RoIGxlc3MgdGhhbiB3YXRlcm1hcmsnLCBkb1JlYWQpO1xuICB9XG5cbiAgLy8gaG93ZXZlciwgaWYgd2UndmUgZW5kZWQsIHRoZW4gdGhlcmUncyBubyBwb2ludCwgYW5kIGlmIHdlJ3JlIGFscmVhZHlcbiAgLy8gcmVhZGluZywgdGhlbiBpdCdzIHVubmVjZXNzYXJ5LlxuICBpZiAoc3RhdGUuZW5kZWQgfHwgc3RhdGUucmVhZGluZykge1xuICAgIGRvUmVhZCA9IGZhbHNlO1xuICAgIGRlYnVnKCdyZWFkaW5nIG9yIGVuZGVkJywgZG9SZWFkKTtcbiAgfSBlbHNlIGlmIChkb1JlYWQpIHtcbiAgICBkZWJ1ZygnZG8gcmVhZCcpO1xuICAgIHN0YXRlLnJlYWRpbmcgPSB0cnVlO1xuICAgIHN0YXRlLnN5bmMgPSB0cnVlO1xuICAgIC8vIGlmIHRoZSBsZW5ndGggaXMgY3VycmVudGx5IHplcm8sIHRoZW4gd2UgKm5lZWQqIGEgcmVhZGFibGUgZXZlbnQuXG4gICAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCkgc3RhdGUubmVlZFJlYWRhYmxlID0gdHJ1ZTtcbiAgICAvLyBjYWxsIGludGVybmFsIHJlYWQgbWV0aG9kXG4gICAgdGhpcy5fcmVhZChzdGF0ZS5oaWdoV2F0ZXJNYXJrKTtcbiAgICBzdGF0ZS5zeW5jID0gZmFsc2U7XG4gICAgLy8gSWYgX3JlYWQgcHVzaGVkIGRhdGEgc3luY2hyb25vdXNseSwgdGhlbiBgcmVhZGluZ2Agd2lsbCBiZSBmYWxzZSxcbiAgICAvLyBhbmQgd2UgbmVlZCB0byByZS1ldmFsdWF0ZSBob3cgbXVjaCBkYXRhIHdlIGNhbiByZXR1cm4gdG8gdGhlIHVzZXIuXG4gICAgaWYgKCFzdGF0ZS5yZWFkaW5nKSBuID0gaG93TXVjaFRvUmVhZChuT3JpZywgc3RhdGUpO1xuICB9XG5cbiAgdmFyIHJldDtcbiAgaWYgKG4gPiAwKSByZXQgPSBmcm9tTGlzdChuLCBzdGF0ZSk7ZWxzZSByZXQgPSBudWxsO1xuXG4gIGlmIChyZXQgPT09IG51bGwpIHtcbiAgICBzdGF0ZS5uZWVkUmVhZGFibGUgPSB0cnVlO1xuICAgIG4gPSAwO1xuICB9IGVsc2Uge1xuICAgIHN0YXRlLmxlbmd0aCAtPSBuO1xuICB9XG5cbiAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCkge1xuICAgIC8vIElmIHdlIGhhdmUgbm90aGluZyBpbiB0aGUgYnVmZmVyLCB0aGVuIHdlIHdhbnQgdG8ga25vd1xuICAgIC8vIGFzIHNvb24gYXMgd2UgKmRvKiBnZXQgc29tZXRoaW5nIGludG8gdGhlIGJ1ZmZlci5cbiAgICBpZiAoIXN0YXRlLmVuZGVkKSBzdGF0ZS5uZWVkUmVhZGFibGUgPSB0cnVlO1xuXG4gICAgLy8gSWYgd2UgdHJpZWQgdG8gcmVhZCgpIHBhc3QgdGhlIEVPRiwgdGhlbiBlbWl0IGVuZCBvbiB0aGUgbmV4dCB0aWNrLlxuICAgIGlmIChuT3JpZyAhPT0gbiAmJiBzdGF0ZS5lbmRlZCkgZW5kUmVhZGFibGUodGhpcyk7XG4gIH1cblxuICBpZiAocmV0ICE9PSBudWxsKSB0aGlzLmVtaXQoJ2RhdGEnLCByZXQpO1xuXG4gIHJldHVybiByZXQ7XG59O1xuXG5mdW5jdGlvbiBvbkVvZkNodW5rKHN0cmVhbSwgc3RhdGUpIHtcbiAgaWYgKHN0YXRlLmVuZGVkKSByZXR1cm47XG4gIGlmIChzdGF0ZS5kZWNvZGVyKSB7XG4gICAgdmFyIGNodW5rID0gc3RhdGUuZGVjb2Rlci5lbmQoKTtcbiAgICBpZiAoY2h1bmsgJiYgY2h1bmsubGVuZ3RoKSB7XG4gICAgICBzdGF0ZS5idWZmZXIucHVzaChjaHVuayk7XG4gICAgICBzdGF0ZS5sZW5ndGggKz0gc3RhdGUub2JqZWN0TW9kZSA/IDEgOiBjaHVuay5sZW5ndGg7XG4gICAgfVxuICB9XG4gIHN0YXRlLmVuZGVkID0gdHJ1ZTtcblxuICAvLyBlbWl0ICdyZWFkYWJsZScgbm93IHRvIG1ha2Ugc3VyZSBpdCBnZXRzIHBpY2tlZCB1cC5cbiAgZW1pdFJlYWRhYmxlKHN0cmVhbSk7XG59XG5cbi8vIERvbid0IGVtaXQgcmVhZGFibGUgcmlnaHQgYXdheSBpbiBzeW5jIG1vZGUsIGJlY2F1c2UgdGhpcyBjYW4gdHJpZ2dlclxuLy8gYW5vdGhlciByZWFkKCkgY2FsbCA9PiBzdGFjayBvdmVyZmxvdy4gIFRoaXMgd2F5LCBpdCBtaWdodCB0cmlnZ2VyXG4vLyBhIG5leHRUaWNrIHJlY3Vyc2lvbiB3YXJuaW5nLCBidXQgdGhhdCdzIG5vdCBzbyBiYWQuXG5mdW5jdGlvbiBlbWl0UmVhZGFibGUoc3RyZWFtKSB7XG4gIHZhciBzdGF0ZSA9IHN0cmVhbS5fcmVhZGFibGVTdGF0ZTtcbiAgc3RhdGUubmVlZFJlYWRhYmxlID0gZmFsc2U7XG4gIGlmICghc3RhdGUuZW1pdHRlZFJlYWRhYmxlKSB7XG4gICAgZGVidWcoJ2VtaXRSZWFkYWJsZScsIHN0YXRlLmZsb3dpbmcpO1xuICAgIHN0YXRlLmVtaXR0ZWRSZWFkYWJsZSA9IHRydWU7XG4gICAgaWYgKHN0YXRlLnN5bmMpIHBuYS5uZXh0VGljayhlbWl0UmVhZGFibGVfLCBzdHJlYW0pO2Vsc2UgZW1pdFJlYWRhYmxlXyhzdHJlYW0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVtaXRSZWFkYWJsZV8oc3RyZWFtKSB7XG4gIGRlYnVnKCdlbWl0IHJlYWRhYmxlJyk7XG4gIHN0cmVhbS5lbWl0KCdyZWFkYWJsZScpO1xuICBmbG93KHN0cmVhbSk7XG59XG5cbi8vIGF0IHRoaXMgcG9pbnQsIHRoZSB1c2VyIGhhcyBwcmVzdW1hYmx5IHNlZW4gdGhlICdyZWFkYWJsZScgZXZlbnQsXG4vLyBhbmQgY2FsbGVkIHJlYWQoKSB0byBjb25zdW1lIHNvbWUgZGF0YS4gIHRoYXQgbWF5IGhhdmUgdHJpZ2dlcmVkXG4vLyBpbiB0dXJuIGFub3RoZXIgX3JlYWQobikgY2FsbCwgaW4gd2hpY2ggY2FzZSByZWFkaW5nID0gdHJ1ZSBpZlxuLy8gaXQncyBpbiBwcm9ncmVzcy5cbi8vIEhvd2V2ZXIsIGlmIHdlJ3JlIG5vdCBlbmRlZCwgb3IgcmVhZGluZywgYW5kIHRoZSBsZW5ndGggPCBod20sXG4vLyB0aGVuIGdvIGFoZWFkIGFuZCB0cnkgdG8gcmVhZCBzb21lIG1vcmUgcHJlZW1wdGl2ZWx5LlxuZnVuY3Rpb24gbWF5YmVSZWFkTW9yZShzdHJlYW0sIHN0YXRlKSB7XG4gIGlmICghc3RhdGUucmVhZGluZ01vcmUpIHtcbiAgICBzdGF0ZS5yZWFkaW5nTW9yZSA9IHRydWU7XG4gICAgcG5hLm5leHRUaWNrKG1heWJlUmVhZE1vcmVfLCBzdHJlYW0sIHN0YXRlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXliZVJlYWRNb3JlXyhzdHJlYW0sIHN0YXRlKSB7XG4gIHZhciBsZW4gPSBzdGF0ZS5sZW5ndGg7XG4gIHdoaWxlICghc3RhdGUucmVhZGluZyAmJiAhc3RhdGUuZmxvd2luZyAmJiAhc3RhdGUuZW5kZWQgJiYgc3RhdGUubGVuZ3RoIDwgc3RhdGUuaGlnaFdhdGVyTWFyaykge1xuICAgIGRlYnVnKCdtYXliZVJlYWRNb3JlIHJlYWQgMCcpO1xuICAgIHN0cmVhbS5yZWFkKDApO1xuICAgIGlmIChsZW4gPT09IHN0YXRlLmxlbmd0aClcbiAgICAgIC8vIGRpZG4ndCBnZXQgYW55IGRhdGEsIHN0b3Agc3Bpbm5pbmcuXG4gICAgICBicmVhaztlbHNlIGxlbiA9IHN0YXRlLmxlbmd0aDtcbiAgfVxuICBzdGF0ZS5yZWFkaW5nTW9yZSA9IGZhbHNlO1xufVxuXG4vLyBhYnN0cmFjdCBtZXRob2QuICB0byBiZSBvdmVycmlkZGVuIGluIHNwZWNpZmljIGltcGxlbWVudGF0aW9uIGNsYXNzZXMuXG4vLyBjYWxsIGNiKGVyLCBkYXRhKSB3aGVyZSBkYXRhIGlzIDw9IG4gaW4gbGVuZ3RoLlxuLy8gZm9yIHZpcnR1YWwgKG5vbi1zdHJpbmcsIG5vbi1idWZmZXIpIHN0cmVhbXMsIFwibGVuZ3RoXCIgaXMgc29tZXdoYXRcbi8vIGFyYml0cmFyeSwgYW5kIHBlcmhhcHMgbm90IHZlcnkgbWVhbmluZ2Z1bC5cblJlYWRhYmxlLnByb3RvdHlwZS5fcmVhZCA9IGZ1bmN0aW9uIChuKSB7XG4gIHRoaXMuZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IoJ19yZWFkKCkgaXMgbm90IGltcGxlbWVudGVkJykpO1xufTtcblxuUmVhZGFibGUucHJvdG90eXBlLnBpcGUgPSBmdW5jdGlvbiAoZGVzdCwgcGlwZU9wdHMpIHtcbiAgdmFyIHNyYyA9IHRoaXM7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG5cbiAgc3dpdGNoIChzdGF0ZS5waXBlc0NvdW50KSB7XG4gICAgY2FzZSAwOlxuICAgICAgc3RhdGUucGlwZXMgPSBkZXN0O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAxOlxuICAgICAgc3RhdGUucGlwZXMgPSBbc3RhdGUucGlwZXMsIGRlc3RdO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHN0YXRlLnBpcGVzLnB1c2goZGVzdCk7XG4gICAgICBicmVhaztcbiAgfVxuICBzdGF0ZS5waXBlc0NvdW50ICs9IDE7XG4gIGRlYnVnKCdwaXBlIGNvdW50PSVkIG9wdHM9JWonLCBzdGF0ZS5waXBlc0NvdW50LCBwaXBlT3B0cyk7XG5cbiAgdmFyIGRvRW5kID0gKCFwaXBlT3B0cyB8fCBwaXBlT3B0cy5lbmQgIT09IGZhbHNlKSAmJiBkZXN0ICE9PSBwcm9jZXNzLnN0ZG91dCAmJiBkZXN0ICE9PSBwcm9jZXNzLnN0ZGVycjtcblxuICB2YXIgZW5kRm4gPSBkb0VuZCA/IG9uZW5kIDogdW5waXBlO1xuICBpZiAoc3RhdGUuZW5kRW1pdHRlZCkgcG5hLm5leHRUaWNrKGVuZEZuKTtlbHNlIHNyYy5vbmNlKCdlbmQnLCBlbmRGbik7XG5cbiAgZGVzdC5vbigndW5waXBlJywgb251bnBpcGUpO1xuICBmdW5jdGlvbiBvbnVucGlwZShyZWFkYWJsZSwgdW5waXBlSW5mbykge1xuICAgIGRlYnVnKCdvbnVucGlwZScpO1xuICAgIGlmIChyZWFkYWJsZSA9PT0gc3JjKSB7XG4gICAgICBpZiAodW5waXBlSW5mbyAmJiB1bnBpcGVJbmZvLmhhc1VucGlwZWQgPT09IGZhbHNlKSB7XG4gICAgICAgIHVucGlwZUluZm8uaGFzVW5waXBlZCA9IHRydWU7XG4gICAgICAgIGNsZWFudXAoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBvbmVuZCgpIHtcbiAgICBkZWJ1Zygnb25lbmQnKTtcbiAgICBkZXN0LmVuZCgpO1xuICB9XG5cbiAgLy8gd2hlbiB0aGUgZGVzdCBkcmFpbnMsIGl0IHJlZHVjZXMgdGhlIGF3YWl0RHJhaW4gY291bnRlclxuICAvLyBvbiB0aGUgc291cmNlLiAgVGhpcyB3b3VsZCBiZSBtb3JlIGVsZWdhbnQgd2l0aCBhIC5vbmNlKClcbiAgLy8gaGFuZGxlciBpbiBmbG93KCksIGJ1dCBhZGRpbmcgYW5kIHJlbW92aW5nIHJlcGVhdGVkbHkgaXNcbiAgLy8gdG9vIHNsb3cuXG4gIHZhciBvbmRyYWluID0gcGlwZU9uRHJhaW4oc3JjKTtcbiAgZGVzdC5vbignZHJhaW4nLCBvbmRyYWluKTtcblxuICB2YXIgY2xlYW5lZFVwID0gZmFsc2U7XG4gIGZ1bmN0aW9uIGNsZWFudXAoKSB7XG4gICAgZGVidWcoJ2NsZWFudXAnKTtcbiAgICAvLyBjbGVhbnVwIGV2ZW50IGhhbmRsZXJzIG9uY2UgdGhlIHBpcGUgaXMgYnJva2VuXG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignY2xvc2UnLCBvbmNsb3NlKTtcbiAgICBkZXN0LnJlbW92ZUxpc3RlbmVyKCdmaW5pc2gnLCBvbmZpbmlzaCk7XG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignZHJhaW4nLCBvbmRyYWluKTtcbiAgICBkZXN0LnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIG9uZXJyb3IpO1xuICAgIGRlc3QucmVtb3ZlTGlzdGVuZXIoJ3VucGlwZScsIG9udW5waXBlKTtcbiAgICBzcmMucmVtb3ZlTGlzdGVuZXIoJ2VuZCcsIG9uZW5kKTtcbiAgICBzcmMucmVtb3ZlTGlzdGVuZXIoJ2VuZCcsIHVucGlwZSk7XG4gICAgc3JjLnJlbW92ZUxpc3RlbmVyKCdkYXRhJywgb25kYXRhKTtcblxuICAgIGNsZWFuZWRVcCA9IHRydWU7XG5cbiAgICAvLyBpZiB0aGUgcmVhZGVyIGlzIHdhaXRpbmcgZm9yIGEgZHJhaW4gZXZlbnQgZnJvbSB0aGlzXG4gICAgLy8gc3BlY2lmaWMgd3JpdGVyLCB0aGVuIGl0IHdvdWxkIGNhdXNlIGl0IHRvIG5ldmVyIHN0YXJ0XG4gICAgLy8gZmxvd2luZyBhZ2Fpbi5cbiAgICAvLyBTbywgaWYgdGhpcyBpcyBhd2FpdGluZyBhIGRyYWluLCB0aGVuIHdlIGp1c3QgY2FsbCBpdCBub3cuXG4gICAgLy8gSWYgd2UgZG9uJ3Qga25vdywgdGhlbiBhc3N1bWUgdGhhdCB3ZSBhcmUgd2FpdGluZyBmb3Igb25lLlxuICAgIGlmIChzdGF0ZS5hd2FpdERyYWluICYmICghZGVzdC5fd3JpdGFibGVTdGF0ZSB8fCBkZXN0Ll93cml0YWJsZVN0YXRlLm5lZWREcmFpbikpIG9uZHJhaW4oKTtcbiAgfVxuXG4gIC8vIElmIHRoZSB1c2VyIHB1c2hlcyBtb3JlIGRhdGEgd2hpbGUgd2UncmUgd3JpdGluZyB0byBkZXN0IHRoZW4gd2UnbGwgZW5kIHVwXG4gIC8vIGluIG9uZGF0YSBhZ2Fpbi4gSG93ZXZlciwgd2Ugb25seSB3YW50IHRvIGluY3JlYXNlIGF3YWl0RHJhaW4gb25jZSBiZWNhdXNlXG4gIC8vIGRlc3Qgd2lsbCBvbmx5IGVtaXQgb25lICdkcmFpbicgZXZlbnQgZm9yIHRoZSBtdWx0aXBsZSB3cml0ZXMuXG4gIC8vID0+IEludHJvZHVjZSBhIGd1YXJkIG9uIGluY3JlYXNpbmcgYXdhaXREcmFpbi5cbiAgdmFyIGluY3JlYXNlZEF3YWl0RHJhaW4gPSBmYWxzZTtcbiAgc3JjLm9uKCdkYXRhJywgb25kYXRhKTtcbiAgZnVuY3Rpb24gb25kYXRhKGNodW5rKSB7XG4gICAgZGVidWcoJ29uZGF0YScpO1xuICAgIGluY3JlYXNlZEF3YWl0RHJhaW4gPSBmYWxzZTtcbiAgICB2YXIgcmV0ID0gZGVzdC53cml0ZShjaHVuayk7XG4gICAgaWYgKGZhbHNlID09PSByZXQgJiYgIWluY3JlYXNlZEF3YWl0RHJhaW4pIHtcbiAgICAgIC8vIElmIHRoZSB1c2VyIHVucGlwZWQgZHVyaW5nIGBkZXN0LndyaXRlKClgLCBpdCBpcyBwb3NzaWJsZVxuICAgICAgLy8gdG8gZ2V0IHN0dWNrIGluIGEgcGVybWFuZW50bHkgcGF1c2VkIHN0YXRlIGlmIHRoYXQgd3JpdGVcbiAgICAgIC8vIGFsc28gcmV0dXJuZWQgZmFsc2UuXG4gICAgICAvLyA9PiBDaGVjayB3aGV0aGVyIGBkZXN0YCBpcyBzdGlsbCBhIHBpcGluZyBkZXN0aW5hdGlvbi5cbiAgICAgIGlmICgoc3RhdGUucGlwZXNDb3VudCA9PT0gMSAmJiBzdGF0ZS5waXBlcyA9PT0gZGVzdCB8fCBzdGF0ZS5waXBlc0NvdW50ID4gMSAmJiBpbmRleE9mKHN0YXRlLnBpcGVzLCBkZXN0KSAhPT0gLTEpICYmICFjbGVhbmVkVXApIHtcbiAgICAgICAgZGVidWcoJ2ZhbHNlIHdyaXRlIHJlc3BvbnNlLCBwYXVzZScsIHNyYy5fcmVhZGFibGVTdGF0ZS5hd2FpdERyYWluKTtcbiAgICAgICAgc3JjLl9yZWFkYWJsZVN0YXRlLmF3YWl0RHJhaW4rKztcbiAgICAgICAgaW5jcmVhc2VkQXdhaXREcmFpbiA9IHRydWU7XG4gICAgICB9XG4gICAgICBzcmMucGF1c2UoKTtcbiAgICB9XG4gIH1cblxuICAvLyBpZiB0aGUgZGVzdCBoYXMgYW4gZXJyb3IsIHRoZW4gc3RvcCBwaXBpbmcgaW50byBpdC5cbiAgLy8gaG93ZXZlciwgZG9uJ3Qgc3VwcHJlc3MgdGhlIHRocm93aW5nIGJlaGF2aW9yIGZvciB0aGlzLlxuICBmdW5jdGlvbiBvbmVycm9yKGVyKSB7XG4gICAgZGVidWcoJ29uZXJyb3InLCBlcik7XG4gICAgdW5waXBlKCk7XG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCBvbmVycm9yKTtcbiAgICBpZiAoRUVsaXN0ZW5lckNvdW50KGRlc3QsICdlcnJvcicpID09PSAwKSBkZXN0LmVtaXQoJ2Vycm9yJywgZXIpO1xuICB9XG5cbiAgLy8gTWFrZSBzdXJlIG91ciBlcnJvciBoYW5kbGVyIGlzIGF0dGFjaGVkIGJlZm9yZSB1c2VybGFuZCBvbmVzLlxuICBwcmVwZW5kTGlzdGVuZXIoZGVzdCwgJ2Vycm9yJywgb25lcnJvcik7XG5cbiAgLy8gQm90aCBjbG9zZSBhbmQgZmluaXNoIHNob3VsZCB0cmlnZ2VyIHVucGlwZSwgYnV0IG9ubHkgb25jZS5cbiAgZnVuY3Rpb24gb25jbG9zZSgpIHtcbiAgICBkZXN0LnJlbW92ZUxpc3RlbmVyKCdmaW5pc2gnLCBvbmZpbmlzaCk7XG4gICAgdW5waXBlKCk7XG4gIH1cbiAgZGVzdC5vbmNlKCdjbG9zZScsIG9uY2xvc2UpO1xuICBmdW5jdGlvbiBvbmZpbmlzaCgpIHtcbiAgICBkZWJ1Zygnb25maW5pc2gnKTtcbiAgICBkZXN0LnJlbW92ZUxpc3RlbmVyKCdjbG9zZScsIG9uY2xvc2UpO1xuICAgIHVucGlwZSgpO1xuICB9XG4gIGRlc3Qub25jZSgnZmluaXNoJywgb25maW5pc2gpO1xuXG4gIGZ1bmN0aW9uIHVucGlwZSgpIHtcbiAgICBkZWJ1ZygndW5waXBlJyk7XG4gICAgc3JjLnVucGlwZShkZXN0KTtcbiAgfVxuXG4gIC8vIHRlbGwgdGhlIGRlc3QgdGhhdCBpdCdzIGJlaW5nIHBpcGVkIHRvXG4gIGRlc3QuZW1pdCgncGlwZScsIHNyYyk7XG5cbiAgLy8gc3RhcnQgdGhlIGZsb3cgaWYgaXQgaGFzbid0IGJlZW4gc3RhcnRlZCBhbHJlYWR5LlxuICBpZiAoIXN0YXRlLmZsb3dpbmcpIHtcbiAgICBkZWJ1ZygncGlwZSByZXN1bWUnKTtcbiAgICBzcmMucmVzdW1lKCk7XG4gIH1cblxuICByZXR1cm4gZGVzdDtcbn07XG5cbmZ1bmN0aW9uIHBpcGVPbkRyYWluKHNyYykge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdGF0ZSA9IHNyYy5fcmVhZGFibGVTdGF0ZTtcbiAgICBkZWJ1ZygncGlwZU9uRHJhaW4nLCBzdGF0ZS5hd2FpdERyYWluKTtcbiAgICBpZiAoc3RhdGUuYXdhaXREcmFpbikgc3RhdGUuYXdhaXREcmFpbi0tO1xuICAgIGlmIChzdGF0ZS5hd2FpdERyYWluID09PSAwICYmIEVFbGlzdGVuZXJDb3VudChzcmMsICdkYXRhJykpIHtcbiAgICAgIHN0YXRlLmZsb3dpbmcgPSB0cnVlO1xuICAgICAgZmxvdyhzcmMpO1xuICAgIH1cbiAgfTtcbn1cblxuUmVhZGFibGUucHJvdG90eXBlLnVucGlwZSA9IGZ1bmN0aW9uIChkZXN0KSB7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gIHZhciB1bnBpcGVJbmZvID0geyBoYXNVbnBpcGVkOiBmYWxzZSB9O1xuXG4gIC8vIGlmIHdlJ3JlIG5vdCBwaXBpbmcgYW55d2hlcmUsIHRoZW4gZG8gbm90aGluZy5cbiAgaWYgKHN0YXRlLnBpcGVzQ291bnQgPT09IDApIHJldHVybiB0aGlzO1xuXG4gIC8vIGp1c3Qgb25lIGRlc3RpbmF0aW9uLiAgbW9zdCBjb21tb24gY2FzZS5cbiAgaWYgKHN0YXRlLnBpcGVzQ291bnQgPT09IDEpIHtcbiAgICAvLyBwYXNzZWQgaW4gb25lLCBidXQgaXQncyBub3QgdGhlIHJpZ2h0IG9uZS5cbiAgICBpZiAoZGVzdCAmJiBkZXN0ICE9PSBzdGF0ZS5waXBlcykgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAoIWRlc3QpIGRlc3QgPSBzdGF0ZS5waXBlcztcblxuICAgIC8vIGdvdCBhIG1hdGNoLlxuICAgIHN0YXRlLnBpcGVzID0gbnVsbDtcbiAgICBzdGF0ZS5waXBlc0NvdW50ID0gMDtcbiAgICBzdGF0ZS5mbG93aW5nID0gZmFsc2U7XG4gICAgaWYgKGRlc3QpIGRlc3QuZW1pdCgndW5waXBlJywgdGhpcywgdW5waXBlSW5mbyk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvLyBzbG93IGNhc2UuIG11bHRpcGxlIHBpcGUgZGVzdGluYXRpb25zLlxuXG4gIGlmICghZGVzdCkge1xuICAgIC8vIHJlbW92ZSBhbGwuXG4gICAgdmFyIGRlc3RzID0gc3RhdGUucGlwZXM7XG4gICAgdmFyIGxlbiA9IHN0YXRlLnBpcGVzQ291bnQ7XG4gICAgc3RhdGUucGlwZXMgPSBudWxsO1xuICAgIHN0YXRlLnBpcGVzQ291bnQgPSAwO1xuICAgIHN0YXRlLmZsb3dpbmcgPSBmYWxzZTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIGRlc3RzW2ldLmVtaXQoJ3VucGlwZScsIHRoaXMsIHVucGlwZUluZm8pO1xuICAgIH1yZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8vIHRyeSB0byBmaW5kIHRoZSByaWdodCBvbmUuXG4gIHZhciBpbmRleCA9IGluZGV4T2Yoc3RhdGUucGlwZXMsIGRlc3QpO1xuICBpZiAoaW5kZXggPT09IC0xKSByZXR1cm4gdGhpcztcblxuICBzdGF0ZS5waXBlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICBzdGF0ZS5waXBlc0NvdW50IC09IDE7XG4gIGlmIChzdGF0ZS5waXBlc0NvdW50ID09PSAxKSBzdGF0ZS5waXBlcyA9IHN0YXRlLnBpcGVzWzBdO1xuXG4gIGRlc3QuZW1pdCgndW5waXBlJywgdGhpcywgdW5waXBlSW5mbyk7XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBzZXQgdXAgZGF0YSBldmVudHMgaWYgdGhleSBhcmUgYXNrZWQgZm9yXG4vLyBFbnN1cmUgcmVhZGFibGUgbGlzdGVuZXJzIGV2ZW50dWFsbHkgZ2V0IHNvbWV0aGluZ1xuUmVhZGFibGUucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gKGV2LCBmbikge1xuICB2YXIgcmVzID0gU3RyZWFtLnByb3RvdHlwZS5vbi5jYWxsKHRoaXMsIGV2LCBmbik7XG5cbiAgaWYgKGV2ID09PSAnZGF0YScpIHtcbiAgICAvLyBTdGFydCBmbG93aW5nIG9uIG5leHQgdGljayBpZiBzdHJlYW0gaXNuJ3QgZXhwbGljaXRseSBwYXVzZWRcbiAgICBpZiAodGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nICE9PSBmYWxzZSkgdGhpcy5yZXN1bWUoKTtcbiAgfSBlbHNlIGlmIChldiA9PT0gJ3JlYWRhYmxlJykge1xuICAgIHZhciBzdGF0ZSA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gICAgaWYgKCFzdGF0ZS5lbmRFbWl0dGVkICYmICFzdGF0ZS5yZWFkYWJsZUxpc3RlbmluZykge1xuICAgICAgc3RhdGUucmVhZGFibGVMaXN0ZW5pbmcgPSBzdGF0ZS5uZWVkUmVhZGFibGUgPSB0cnVlO1xuICAgICAgc3RhdGUuZW1pdHRlZFJlYWRhYmxlID0gZmFsc2U7XG4gICAgICBpZiAoIXN0YXRlLnJlYWRpbmcpIHtcbiAgICAgICAgcG5hLm5leHRUaWNrKG5SZWFkaW5nTmV4dFRpY2ssIHRoaXMpO1xuICAgICAgfSBlbHNlIGlmIChzdGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgZW1pdFJlYWRhYmxlKHRoaXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXM7XG59O1xuUmVhZGFibGUucHJvdG90eXBlLmFkZExpc3RlbmVyID0gUmVhZGFibGUucHJvdG90eXBlLm9uO1xuXG5mdW5jdGlvbiBuUmVhZGluZ05leHRUaWNrKHNlbGYpIHtcbiAgZGVidWcoJ3JlYWRhYmxlIG5leHR0aWNrIHJlYWQgMCcpO1xuICBzZWxmLnJlYWQoMCk7XG59XG5cbi8vIHBhdXNlKCkgYW5kIHJlc3VtZSgpIGFyZSByZW1uYW50cyBvZiB0aGUgbGVnYWN5IHJlYWRhYmxlIHN0cmVhbSBBUElcbi8vIElmIHRoZSB1c2VyIHVzZXMgdGhlbSwgdGhlbiBzd2l0Y2ggaW50byBvbGQgbW9kZS5cblJlYWRhYmxlLnByb3RvdHlwZS5yZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gIGlmICghc3RhdGUuZmxvd2luZykge1xuICAgIGRlYnVnKCdyZXN1bWUnKTtcbiAgICBzdGF0ZS5mbG93aW5nID0gdHJ1ZTtcbiAgICByZXN1bWUodGhpcywgc3RhdGUpO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gcmVzdW1lKHN0cmVhbSwgc3RhdGUpIHtcbiAgaWYgKCFzdGF0ZS5yZXN1bWVTY2hlZHVsZWQpIHtcbiAgICBzdGF0ZS5yZXN1bWVTY2hlZHVsZWQgPSB0cnVlO1xuICAgIHBuYS5uZXh0VGljayhyZXN1bWVfLCBzdHJlYW0sIHN0YXRlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZXN1bWVfKHN0cmVhbSwgc3RhdGUpIHtcbiAgaWYgKCFzdGF0ZS5yZWFkaW5nKSB7XG4gICAgZGVidWcoJ3Jlc3VtZSByZWFkIDAnKTtcbiAgICBzdHJlYW0ucmVhZCgwKTtcbiAgfVxuXG4gIHN0YXRlLnJlc3VtZVNjaGVkdWxlZCA9IGZhbHNlO1xuICBzdGF0ZS5hd2FpdERyYWluID0gMDtcbiAgc3RyZWFtLmVtaXQoJ3Jlc3VtZScpO1xuICBmbG93KHN0cmVhbSk7XG4gIGlmIChzdGF0ZS5mbG93aW5nICYmICFzdGF0ZS5yZWFkaW5nKSBzdHJlYW0ucmVhZCgwKTtcbn1cblxuUmVhZGFibGUucHJvdG90eXBlLnBhdXNlID0gZnVuY3Rpb24gKCkge1xuICBkZWJ1ZygnY2FsbCBwYXVzZSBmbG93aW5nPSVqJywgdGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nKTtcbiAgaWYgKGZhbHNlICE9PSB0aGlzLl9yZWFkYWJsZVN0YXRlLmZsb3dpbmcpIHtcbiAgICBkZWJ1ZygncGF1c2UnKTtcbiAgICB0aGlzLl9yZWFkYWJsZVN0YXRlLmZsb3dpbmcgPSBmYWxzZTtcbiAgICB0aGlzLmVtaXQoJ3BhdXNlJyk7XG4gIH1cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiBmbG93KHN0cmVhbSkge1xuICB2YXIgc3RhdGUgPSBzdHJlYW0uX3JlYWRhYmxlU3RhdGU7XG4gIGRlYnVnKCdmbG93Jywgc3RhdGUuZmxvd2luZyk7XG4gIHdoaWxlIChzdGF0ZS5mbG93aW5nICYmIHN0cmVhbS5yZWFkKCkgIT09IG51bGwpIHt9XG59XG5cbi8vIHdyYXAgYW4gb2xkLXN0eWxlIHN0cmVhbSBhcyB0aGUgYXN5bmMgZGF0YSBzb3VyY2UuXG4vLyBUaGlzIGlzICpub3QqIHBhcnQgb2YgdGhlIHJlYWRhYmxlIHN0cmVhbSBpbnRlcmZhY2UuXG4vLyBJdCBpcyBhbiB1Z2x5IHVuZm9ydHVuYXRlIG1lc3Mgb2YgaGlzdG9yeS5cblJlYWRhYmxlLnByb3RvdHlwZS53cmFwID0gZnVuY3Rpb24gKHN0cmVhbSkge1xuICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gIHZhciBzdGF0ZSA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gIHZhciBwYXVzZWQgPSBmYWxzZTtcblxuICBzdHJlYW0ub24oJ2VuZCcsIGZ1bmN0aW9uICgpIHtcbiAgICBkZWJ1Zygnd3JhcHBlZCBlbmQnKTtcbiAgICBpZiAoc3RhdGUuZGVjb2RlciAmJiAhc3RhdGUuZW5kZWQpIHtcbiAgICAgIHZhciBjaHVuayA9IHN0YXRlLmRlY29kZXIuZW5kKCk7XG4gICAgICBpZiAoY2h1bmsgJiYgY2h1bmsubGVuZ3RoKSBfdGhpcy5wdXNoKGNodW5rKTtcbiAgICB9XG5cbiAgICBfdGhpcy5wdXNoKG51bGwpO1xuICB9KTtcblxuICBzdHJlYW0ub24oJ2RhdGEnLCBmdW5jdGlvbiAoY2h1bmspIHtcbiAgICBkZWJ1Zygnd3JhcHBlZCBkYXRhJyk7XG4gICAgaWYgKHN0YXRlLmRlY29kZXIpIGNodW5rID0gc3RhdGUuZGVjb2Rlci53cml0ZShjaHVuayk7XG5cbiAgICAvLyBkb24ndCBza2lwIG92ZXIgZmFsc3kgdmFsdWVzIGluIG9iamVjdE1vZGVcbiAgICBpZiAoc3RhdGUub2JqZWN0TW9kZSAmJiAoY2h1bmsgPT09IG51bGwgfHwgY2h1bmsgPT09IHVuZGVmaW5lZCkpIHJldHVybjtlbHNlIGlmICghc3RhdGUub2JqZWN0TW9kZSAmJiAoIWNodW5rIHx8ICFjaHVuay5sZW5ndGgpKSByZXR1cm47XG5cbiAgICB2YXIgcmV0ID0gX3RoaXMucHVzaChjaHVuayk7XG4gICAgaWYgKCFyZXQpIHtcbiAgICAgIHBhdXNlZCA9IHRydWU7XG4gICAgICBzdHJlYW0ucGF1c2UoKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8vIHByb3h5IGFsbCB0aGUgb3RoZXIgbWV0aG9kcy5cbiAgLy8gaW1wb3J0YW50IHdoZW4gd3JhcHBpbmcgZmlsdGVycyBhbmQgZHVwbGV4ZXMuXG4gIGZvciAodmFyIGkgaW4gc3RyZWFtKSB7XG4gICAgaWYgKHRoaXNbaV0gPT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygc3RyZWFtW2ldID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICB0aGlzW2ldID0gZnVuY3Rpb24gKG1ldGhvZCkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBzdHJlYW1bbWV0aG9kXS5hcHBseShzdHJlYW0sIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgICB9KGkpO1xuICAgIH1cbiAgfVxuXG4gIC8vIHByb3h5IGNlcnRhaW4gaW1wb3J0YW50IGV2ZW50cy5cbiAgZm9yICh2YXIgbiA9IDA7IG4gPCBrUHJveHlFdmVudHMubGVuZ3RoOyBuKyspIHtcbiAgICBzdHJlYW0ub24oa1Byb3h5RXZlbnRzW25dLCB0aGlzLmVtaXQuYmluZCh0aGlzLCBrUHJveHlFdmVudHNbbl0pKTtcbiAgfVxuXG4gIC8vIHdoZW4gd2UgdHJ5IHRvIGNvbnN1bWUgc29tZSBtb3JlIGJ5dGVzLCBzaW1wbHkgdW5wYXVzZSB0aGVcbiAgLy8gdW5kZXJseWluZyBzdHJlYW0uXG4gIHRoaXMuX3JlYWQgPSBmdW5jdGlvbiAobikge1xuICAgIGRlYnVnKCd3cmFwcGVkIF9yZWFkJywgbik7XG4gICAgaWYgKHBhdXNlZCkge1xuICAgICAgcGF1c2VkID0gZmFsc2U7XG4gICAgICBzdHJlYW0ucmVzdW1lKCk7XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KFJlYWRhYmxlLnByb3RvdHlwZSwgJ3JlYWRhYmxlSGlnaFdhdGVyTWFyaycsIHtcbiAgLy8gbWFraW5nIGl0IGV4cGxpY2l0IHRoaXMgcHJvcGVydHkgaXMgbm90IGVudW1lcmFibGVcbiAgLy8gYmVjYXVzZSBvdGhlcndpc2Ugc29tZSBwcm90b3R5cGUgbWFuaXB1bGF0aW9uIGluXG4gIC8vIHVzZXJsYW5kIHdpbGwgZmFpbFxuICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGUuaGlnaFdhdGVyTWFyaztcbiAgfVxufSk7XG5cbi8vIGV4cG9zZWQgZm9yIHRlc3RpbmcgcHVycG9zZXMgb25seS5cblJlYWRhYmxlLl9mcm9tTGlzdCA9IGZyb21MaXN0O1xuXG4vLyBQbHVjayBvZmYgbiBieXRlcyBmcm9tIGFuIGFycmF5IG9mIGJ1ZmZlcnMuXG4vLyBMZW5ndGggaXMgdGhlIGNvbWJpbmVkIGxlbmd0aHMgb2YgYWxsIHRoZSBidWZmZXJzIGluIHRoZSBsaXN0LlxuLy8gVGhpcyBmdW5jdGlvbiBpcyBkZXNpZ25lZCB0byBiZSBpbmxpbmFibGUsIHNvIHBsZWFzZSB0YWtlIGNhcmUgd2hlbiBtYWtpbmdcbi8vIGNoYW5nZXMgdG8gdGhlIGZ1bmN0aW9uIGJvZHkuXG5mdW5jdGlvbiBmcm9tTGlzdChuLCBzdGF0ZSkge1xuICAvLyBub3RoaW5nIGJ1ZmZlcmVkXG4gIGlmIChzdGF0ZS5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuXG4gIHZhciByZXQ7XG4gIGlmIChzdGF0ZS5vYmplY3RNb2RlKSByZXQgPSBzdGF0ZS5idWZmZXIuc2hpZnQoKTtlbHNlIGlmICghbiB8fCBuID49IHN0YXRlLmxlbmd0aCkge1xuICAgIC8vIHJlYWQgaXQgYWxsLCB0cnVuY2F0ZSB0aGUgbGlzdFxuICAgIGlmIChzdGF0ZS5kZWNvZGVyKSByZXQgPSBzdGF0ZS5idWZmZXIuam9pbignJyk7ZWxzZSBpZiAoc3RhdGUuYnVmZmVyLmxlbmd0aCA9PT0gMSkgcmV0ID0gc3RhdGUuYnVmZmVyLmhlYWQuZGF0YTtlbHNlIHJldCA9IHN0YXRlLmJ1ZmZlci5jb25jYXQoc3RhdGUubGVuZ3RoKTtcbiAgICBzdGF0ZS5idWZmZXIuY2xlYXIoKTtcbiAgfSBlbHNlIHtcbiAgICAvLyByZWFkIHBhcnQgb2YgbGlzdFxuICAgIHJldCA9IGZyb21MaXN0UGFydGlhbChuLCBzdGF0ZS5idWZmZXIsIHN0YXRlLmRlY29kZXIpO1xuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxuLy8gRXh0cmFjdHMgb25seSBlbm91Z2ggYnVmZmVyZWQgZGF0YSB0byBzYXRpc2Z5IHRoZSBhbW91bnQgcmVxdWVzdGVkLlxuLy8gVGhpcyBmdW5jdGlvbiBpcyBkZXNpZ25lZCB0byBiZSBpbmxpbmFibGUsIHNvIHBsZWFzZSB0YWtlIGNhcmUgd2hlbiBtYWtpbmdcbi8vIGNoYW5nZXMgdG8gdGhlIGZ1bmN0aW9uIGJvZHkuXG5mdW5jdGlvbiBmcm9tTGlzdFBhcnRpYWwobiwgbGlzdCwgaGFzU3RyaW5ncykge1xuICB2YXIgcmV0O1xuICBpZiAobiA8IGxpc3QuaGVhZC5kYXRhLmxlbmd0aCkge1xuICAgIC8vIHNsaWNlIGlzIHRoZSBzYW1lIGZvciBidWZmZXJzIGFuZCBzdHJpbmdzXG4gICAgcmV0ID0gbGlzdC5oZWFkLmRhdGEuc2xpY2UoMCwgbik7XG4gICAgbGlzdC5oZWFkLmRhdGEgPSBsaXN0LmhlYWQuZGF0YS5zbGljZShuKTtcbiAgfSBlbHNlIGlmIChuID09PSBsaXN0LmhlYWQuZGF0YS5sZW5ndGgpIHtcbiAgICAvLyBmaXJzdCBjaHVuayBpcyBhIHBlcmZlY3QgbWF0Y2hcbiAgICByZXQgPSBsaXN0LnNoaWZ0KCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gcmVzdWx0IHNwYW5zIG1vcmUgdGhhbiBvbmUgYnVmZmVyXG4gICAgcmV0ID0gaGFzU3RyaW5ncyA/IGNvcHlGcm9tQnVmZmVyU3RyaW5nKG4sIGxpc3QpIDogY29weUZyb21CdWZmZXIobiwgbGlzdCk7XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuLy8gQ29waWVzIGEgc3BlY2lmaWVkIGFtb3VudCBvZiBjaGFyYWN0ZXJzIGZyb20gdGhlIGxpc3Qgb2YgYnVmZmVyZWQgZGF0YVxuLy8gY2h1bmtzLlxuLy8gVGhpcyBmdW5jdGlvbiBpcyBkZXNpZ25lZCB0byBiZSBpbmxpbmFibGUsIHNvIHBsZWFzZSB0YWtlIGNhcmUgd2hlbiBtYWtpbmdcbi8vIGNoYW5nZXMgdG8gdGhlIGZ1bmN0aW9uIGJvZHkuXG5mdW5jdGlvbiBjb3B5RnJvbUJ1ZmZlclN0cmluZyhuLCBsaXN0KSB7XG4gIHZhciBwID0gbGlzdC5oZWFkO1xuICB2YXIgYyA9IDE7XG4gIHZhciByZXQgPSBwLmRhdGE7XG4gIG4gLT0gcmV0Lmxlbmd0aDtcbiAgd2hpbGUgKHAgPSBwLm5leHQpIHtcbiAgICB2YXIgc3RyID0gcC5kYXRhO1xuICAgIHZhciBuYiA9IG4gPiBzdHIubGVuZ3RoID8gc3RyLmxlbmd0aCA6IG47XG4gICAgaWYgKG5iID09PSBzdHIubGVuZ3RoKSByZXQgKz0gc3RyO2Vsc2UgcmV0ICs9IHN0ci5zbGljZSgwLCBuKTtcbiAgICBuIC09IG5iO1xuICAgIGlmIChuID09PSAwKSB7XG4gICAgICBpZiAobmIgPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgKytjO1xuICAgICAgICBpZiAocC5uZXh0KSBsaXN0LmhlYWQgPSBwLm5leHQ7ZWxzZSBsaXN0LmhlYWQgPSBsaXN0LnRhaWwgPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGlzdC5oZWFkID0gcDtcbiAgICAgICAgcC5kYXRhID0gc3RyLnNsaWNlKG5iKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICArK2M7XG4gIH1cbiAgbGlzdC5sZW5ndGggLT0gYztcbiAgcmV0dXJuIHJldDtcbn1cblxuLy8gQ29waWVzIGEgc3BlY2lmaWVkIGFtb3VudCBvZiBieXRlcyBmcm9tIHRoZSBsaXN0IG9mIGJ1ZmZlcmVkIGRhdGEgY2h1bmtzLlxuLy8gVGhpcyBmdW5jdGlvbiBpcyBkZXNpZ25lZCB0byBiZSBpbmxpbmFibGUsIHNvIHBsZWFzZSB0YWtlIGNhcmUgd2hlbiBtYWtpbmdcbi8vIGNoYW5nZXMgdG8gdGhlIGZ1bmN0aW9uIGJvZHkuXG5mdW5jdGlvbiBjb3B5RnJvbUJ1ZmZlcihuLCBsaXN0KSB7XG4gIHZhciByZXQgPSBCdWZmZXIuYWxsb2NVbnNhZmUobik7XG4gIHZhciBwID0gbGlzdC5oZWFkO1xuICB2YXIgYyA9IDE7XG4gIHAuZGF0YS5jb3B5KHJldCk7XG4gIG4gLT0gcC5kYXRhLmxlbmd0aDtcbiAgd2hpbGUgKHAgPSBwLm5leHQpIHtcbiAgICB2YXIgYnVmID0gcC5kYXRhO1xuICAgIHZhciBuYiA9IG4gPiBidWYubGVuZ3RoID8gYnVmLmxlbmd0aCA6IG47XG4gICAgYnVmLmNvcHkocmV0LCByZXQubGVuZ3RoIC0gbiwgMCwgbmIpO1xuICAgIG4gLT0gbmI7XG4gICAgaWYgKG4gPT09IDApIHtcbiAgICAgIGlmIChuYiA9PT0gYnVmLmxlbmd0aCkge1xuICAgICAgICArK2M7XG4gICAgICAgIGlmIChwLm5leHQpIGxpc3QuaGVhZCA9IHAubmV4dDtlbHNlIGxpc3QuaGVhZCA9IGxpc3QudGFpbCA9IG51bGw7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsaXN0LmhlYWQgPSBwO1xuICAgICAgICBwLmRhdGEgPSBidWYuc2xpY2UobmIpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgfVxuICAgICsrYztcbiAgfVxuICBsaXN0Lmxlbmd0aCAtPSBjO1xuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBlbmRSZWFkYWJsZShzdHJlYW0pIHtcbiAgdmFyIHN0YXRlID0gc3RyZWFtLl9yZWFkYWJsZVN0YXRlO1xuXG4gIC8vIElmIHdlIGdldCBoZXJlIGJlZm9yZSBjb25zdW1pbmcgYWxsIHRoZSBieXRlcywgdGhlbiB0aGF0IGlzIGFcbiAgLy8gYnVnIGluIG5vZGUuICBTaG91bGQgbmV2ZXIgaGFwcGVuLlxuICBpZiAoc3RhdGUubGVuZ3RoID4gMCkgdGhyb3cgbmV3IEVycm9yKCdcImVuZFJlYWRhYmxlKClcIiBjYWxsZWQgb24gbm9uLWVtcHR5IHN0cmVhbScpO1xuXG4gIGlmICghc3RhdGUuZW5kRW1pdHRlZCkge1xuICAgIHN0YXRlLmVuZGVkID0gdHJ1ZTtcbiAgICBwbmEubmV4dFRpY2soZW5kUmVhZGFibGVOVCwgc3RhdGUsIHN0cmVhbSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW5kUmVhZGFibGVOVChzdGF0ZSwgc3RyZWFtKSB7XG4gIC8vIENoZWNrIHRoYXQgd2UgZGlkbid0IGdldCBvbmUgbGFzdCB1bnNoaWZ0LlxuICBpZiAoIXN0YXRlLmVuZEVtaXR0ZWQgJiYgc3RhdGUubGVuZ3RoID09PSAwKSB7XG4gICAgc3RhdGUuZW5kRW1pdHRlZCA9IHRydWU7XG4gICAgc3RyZWFtLnJlYWRhYmxlID0gZmFsc2U7XG4gICAgc3RyZWFtLmVtaXQoJ2VuZCcpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGluZGV4T2YoeHMsIHgpIHtcbiAgZm9yICh2YXIgaSA9IDAsIGwgPSB4cy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICBpZiAoeHNbaV0gPT09IHgpIHJldHVybiBpO1xuICB9XG4gIHJldHVybiAtMTtcbn0iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuLy8gYSB0cmFuc2Zvcm0gc3RyZWFtIGlzIGEgcmVhZGFibGUvd3JpdGFibGUgc3RyZWFtIHdoZXJlIHlvdSBkb1xuLy8gc29tZXRoaW5nIHdpdGggdGhlIGRhdGEuICBTb21ldGltZXMgaXQncyBjYWxsZWQgYSBcImZpbHRlclwiLFxuLy8gYnV0IHRoYXQncyBub3QgYSBncmVhdCBuYW1lIGZvciBpdCwgc2luY2UgdGhhdCBpbXBsaWVzIGEgdGhpbmcgd2hlcmVcbi8vIHNvbWUgYml0cyBwYXNzIHRocm91Z2gsIGFuZCBvdGhlcnMgYXJlIHNpbXBseSBpZ25vcmVkLiAgKFRoYXQgd291bGRcbi8vIGJlIGEgdmFsaWQgZXhhbXBsZSBvZiBhIHRyYW5zZm9ybSwgb2YgY291cnNlLilcbi8vXG4vLyBXaGlsZSB0aGUgb3V0cHV0IGlzIGNhdXNhbGx5IHJlbGF0ZWQgdG8gdGhlIGlucHV0LCBpdCdzIG5vdCBhXG4vLyBuZWNlc3NhcmlseSBzeW1tZXRyaWMgb3Igc3luY2hyb25vdXMgdHJhbnNmb3JtYXRpb24uICBGb3IgZXhhbXBsZSxcbi8vIGEgemxpYiBzdHJlYW0gbWlnaHQgdGFrZSBtdWx0aXBsZSBwbGFpbi10ZXh0IHdyaXRlcygpLCBhbmQgdGhlblxuLy8gZW1pdCBhIHNpbmdsZSBjb21wcmVzc2VkIGNodW5rIHNvbWUgdGltZSBpbiB0aGUgZnV0dXJlLlxuLy9cbi8vIEhlcmUncyBob3cgdGhpcyB3b3Jrczpcbi8vXG4vLyBUaGUgVHJhbnNmb3JtIHN0cmVhbSBoYXMgYWxsIHRoZSBhc3BlY3RzIG9mIHRoZSByZWFkYWJsZSBhbmQgd3JpdGFibGVcbi8vIHN0cmVhbSBjbGFzc2VzLiAgV2hlbiB5b3Ugd3JpdGUoY2h1bmspLCB0aGF0IGNhbGxzIF93cml0ZShjaHVuayxjYilcbi8vIGludGVybmFsbHksIGFuZCByZXR1cm5zIGZhbHNlIGlmIHRoZXJlJ3MgYSBsb3Qgb2YgcGVuZGluZyB3cml0ZXNcbi8vIGJ1ZmZlcmVkIHVwLiAgV2hlbiB5b3UgY2FsbCByZWFkKCksIHRoYXQgY2FsbHMgX3JlYWQobikgdW50aWxcbi8vIHRoZXJlJ3MgZW5vdWdoIHBlbmRpbmcgcmVhZGFibGUgZGF0YSBidWZmZXJlZCB1cC5cbi8vXG4vLyBJbiBhIHRyYW5zZm9ybSBzdHJlYW0sIHRoZSB3cml0dGVuIGRhdGEgaXMgcGxhY2VkIGluIGEgYnVmZmVyLiAgV2hlblxuLy8gX3JlYWQobikgaXMgY2FsbGVkLCBpdCB0cmFuc2Zvcm1zIHRoZSBxdWV1ZWQgdXAgZGF0YSwgY2FsbGluZyB0aGVcbi8vIGJ1ZmZlcmVkIF93cml0ZSBjYidzIGFzIGl0IGNvbnN1bWVzIGNodW5rcy4gIElmIGNvbnN1bWluZyBhIHNpbmdsZVxuLy8gd3JpdHRlbiBjaHVuayB3b3VsZCByZXN1bHQgaW4gbXVsdGlwbGUgb3V0cHV0IGNodW5rcywgdGhlbiB0aGUgZmlyc3Rcbi8vIG91dHB1dHRlZCBiaXQgY2FsbHMgdGhlIHJlYWRjYiwgYW5kIHN1YnNlcXVlbnQgY2h1bmtzIGp1c3QgZ28gaW50b1xuLy8gdGhlIHJlYWQgYnVmZmVyLCBhbmQgd2lsbCBjYXVzZSBpdCB0byBlbWl0ICdyZWFkYWJsZScgaWYgbmVjZXNzYXJ5LlxuLy9cbi8vIFRoaXMgd2F5LCBiYWNrLXByZXNzdXJlIGlzIGFjdHVhbGx5IGRldGVybWluZWQgYnkgdGhlIHJlYWRpbmcgc2lkZSxcbi8vIHNpbmNlIF9yZWFkIGhhcyB0byBiZSBjYWxsZWQgdG8gc3RhcnQgcHJvY2Vzc2luZyBhIG5ldyBjaHVuay4gIEhvd2V2ZXIsXG4vLyBhIHBhdGhvbG9naWNhbCBpbmZsYXRlIHR5cGUgb2YgdHJhbnNmb3JtIGNhbiBjYXVzZSBleGNlc3NpdmUgYnVmZmVyaW5nXG4vLyBoZXJlLiAgRm9yIGV4YW1wbGUsIGltYWdpbmUgYSBzdHJlYW0gd2hlcmUgZXZlcnkgYnl0ZSBvZiBpbnB1dCBpc1xuLy8gaW50ZXJwcmV0ZWQgYXMgYW4gaW50ZWdlciBmcm9tIDAtMjU1LCBhbmQgdGhlbiByZXN1bHRzIGluIHRoYXQgbWFueVxuLy8gYnl0ZXMgb2Ygb3V0cHV0LiAgV3JpdGluZyB0aGUgNCBieXRlcyB7ZmYsZmYsZmYsZmZ9IHdvdWxkIHJlc3VsdCBpblxuLy8gMWtiIG9mIGRhdGEgYmVpbmcgb3V0cHV0LiAgSW4gdGhpcyBjYXNlLCB5b3UgY291bGQgd3JpdGUgYSB2ZXJ5IHNtYWxsXG4vLyBhbW91bnQgb2YgaW5wdXQsIGFuZCBlbmQgdXAgd2l0aCBhIHZlcnkgbGFyZ2UgYW1vdW50IG9mIG91dHB1dC4gIEluXG4vLyBzdWNoIGEgcGF0aG9sb2dpY2FsIGluZmxhdGluZyBtZWNoYW5pc20sIHRoZXJlJ2QgYmUgbm8gd2F5IHRvIHRlbGxcbi8vIHRoZSBzeXN0ZW0gdG8gc3RvcCBkb2luZyB0aGUgdHJhbnNmb3JtLiAgQSBzaW5nbGUgNE1CIHdyaXRlIGNvdWxkXG4vLyBjYXVzZSB0aGUgc3lzdGVtIHRvIHJ1biBvdXQgb2YgbWVtb3J5LlxuLy9cbi8vIEhvd2V2ZXIsIGV2ZW4gaW4gc3VjaCBhIHBhdGhvbG9naWNhbCBjYXNlLCBvbmx5IGEgc2luZ2xlIHdyaXR0ZW4gY2h1bmtcbi8vIHdvdWxkIGJlIGNvbnN1bWVkLCBhbmQgdGhlbiB0aGUgcmVzdCB3b3VsZCB3YWl0ICh1bi10cmFuc2Zvcm1lZCkgdW50aWxcbi8vIHRoZSByZXN1bHRzIG9mIHRoZSBwcmV2aW91cyB0cmFuc2Zvcm1lZCBjaHVuayB3ZXJlIGNvbnN1bWVkLlxuXG4ndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gVHJhbnNmb3JtO1xuXG52YXIgRHVwbGV4ID0gcmVxdWlyZSgnLi9fc3RyZWFtX2R1cGxleCcpO1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIHV0aWwgPSByZXF1aXJlKCdjb3JlLXV0aWwtaXMnKTtcbnV0aWwuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbnV0aWwuaW5oZXJpdHMoVHJhbnNmb3JtLCBEdXBsZXgpO1xuXG5mdW5jdGlvbiBhZnRlclRyYW5zZm9ybShlciwgZGF0YSkge1xuICB2YXIgdHMgPSB0aGlzLl90cmFuc2Zvcm1TdGF0ZTtcbiAgdHMudHJhbnNmb3JtaW5nID0gZmFsc2U7XG5cbiAgdmFyIGNiID0gdHMud3JpdGVjYjtcblxuICBpZiAoIWNiKSB7XG4gICAgcmV0dXJuIHRoaXMuZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IoJ3dyaXRlIGNhbGxiYWNrIGNhbGxlZCBtdWx0aXBsZSB0aW1lcycpKTtcbiAgfVxuXG4gIHRzLndyaXRlY2h1bmsgPSBudWxsO1xuICB0cy53cml0ZWNiID0gbnVsbDtcblxuICBpZiAoZGF0YSAhPSBudWxsKSAvLyBzaW5nbGUgZXF1YWxzIGNoZWNrIGZvciBib3RoIGBudWxsYCBhbmQgYHVuZGVmaW5lZGBcbiAgICB0aGlzLnB1c2goZGF0YSk7XG5cbiAgY2IoZXIpO1xuXG4gIHZhciBycyA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gIHJzLnJlYWRpbmcgPSBmYWxzZTtcbiAgaWYgKHJzLm5lZWRSZWFkYWJsZSB8fCBycy5sZW5ndGggPCBycy5oaWdoV2F0ZXJNYXJrKSB7XG4gICAgdGhpcy5fcmVhZChycy5oaWdoV2F0ZXJNYXJrKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBUcmFuc2Zvcm0ob3B0aW9ucykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgVHJhbnNmb3JtKSkgcmV0dXJuIG5ldyBUcmFuc2Zvcm0ob3B0aW9ucyk7XG5cbiAgRHVwbGV4LmNhbGwodGhpcywgb3B0aW9ucyk7XG5cbiAgdGhpcy5fdHJhbnNmb3JtU3RhdGUgPSB7XG4gICAgYWZ0ZXJUcmFuc2Zvcm06IGFmdGVyVHJhbnNmb3JtLmJpbmQodGhpcyksXG4gICAgbmVlZFRyYW5zZm9ybTogZmFsc2UsXG4gICAgdHJhbnNmb3JtaW5nOiBmYWxzZSxcbiAgICB3cml0ZWNiOiBudWxsLFxuICAgIHdyaXRlY2h1bms6IG51bGwsXG4gICAgd3JpdGVlbmNvZGluZzogbnVsbFxuICB9O1xuXG4gIC8vIHN0YXJ0IG91dCBhc2tpbmcgZm9yIGEgcmVhZGFibGUgZXZlbnQgb25jZSBkYXRhIGlzIHRyYW5zZm9ybWVkLlxuICB0aGlzLl9yZWFkYWJsZVN0YXRlLm5lZWRSZWFkYWJsZSA9IHRydWU7XG5cbiAgLy8gd2UgaGF2ZSBpbXBsZW1lbnRlZCB0aGUgX3JlYWQgbWV0aG9kLCBhbmQgZG9uZSB0aGUgb3RoZXIgdGhpbmdzXG4gIC8vIHRoYXQgUmVhZGFibGUgd2FudHMgYmVmb3JlIHRoZSBmaXJzdCBfcmVhZCBjYWxsLCBzbyB1bnNldCB0aGVcbiAgLy8gc3luYyBndWFyZCBmbGFnLlxuICB0aGlzLl9yZWFkYWJsZVN0YXRlLnN5bmMgPSBmYWxzZTtcblxuICBpZiAob3B0aW9ucykge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy50cmFuc2Zvcm0gPT09ICdmdW5jdGlvbicpIHRoaXMuX3RyYW5zZm9ybSA9IG9wdGlvbnMudHJhbnNmb3JtO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmZsdXNoID09PSAnZnVuY3Rpb24nKSB0aGlzLl9mbHVzaCA9IG9wdGlvbnMuZmx1c2g7XG4gIH1cblxuICAvLyBXaGVuIHRoZSB3cml0YWJsZSBzaWRlIGZpbmlzaGVzLCB0aGVuIGZsdXNoIG91dCBhbnl0aGluZyByZW1haW5pbmcuXG4gIHRoaXMub24oJ3ByZWZpbmlzaCcsIHByZWZpbmlzaCk7XG59XG5cbmZ1bmN0aW9uIHByZWZpbmlzaCgpIHtcbiAgdmFyIF90aGlzID0gdGhpcztcblxuICBpZiAodHlwZW9mIHRoaXMuX2ZsdXNoID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhpcy5fZmx1c2goZnVuY3Rpb24gKGVyLCBkYXRhKSB7XG4gICAgICBkb25lKF90aGlzLCBlciwgZGF0YSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgZG9uZSh0aGlzLCBudWxsLCBudWxsKTtcbiAgfVxufVxuXG5UcmFuc2Zvcm0ucHJvdG90eXBlLnB1c2ggPSBmdW5jdGlvbiAoY2h1bmssIGVuY29kaW5nKSB7XG4gIHRoaXMuX3RyYW5zZm9ybVN0YXRlLm5lZWRUcmFuc2Zvcm0gPSBmYWxzZTtcbiAgcmV0dXJuIER1cGxleC5wcm90b3R5cGUucHVzaC5jYWxsKHRoaXMsIGNodW5rLCBlbmNvZGluZyk7XG59O1xuXG4vLyBUaGlzIGlzIHRoZSBwYXJ0IHdoZXJlIHlvdSBkbyBzdHVmZiFcbi8vIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24gaW4gaW1wbGVtZW50YXRpb24gY2xhc3Nlcy5cbi8vICdjaHVuaycgaXMgYW4gaW5wdXQgY2h1bmsuXG4vL1xuLy8gQ2FsbCBgcHVzaChuZXdDaHVuaylgIHRvIHBhc3MgYWxvbmcgdHJhbnNmb3JtZWQgb3V0cHV0XG4vLyB0byB0aGUgcmVhZGFibGUgc2lkZS4gIFlvdSBtYXkgY2FsbCAncHVzaCcgemVybyBvciBtb3JlIHRpbWVzLlxuLy9cbi8vIENhbGwgYGNiKGVycilgIHdoZW4geW91IGFyZSBkb25lIHdpdGggdGhpcyBjaHVuay4gIElmIHlvdSBwYXNzXG4vLyBhbiBlcnJvciwgdGhlbiB0aGF0J2xsIHB1dCB0aGUgaHVydCBvbiB0aGUgd2hvbGUgb3BlcmF0aW9uLiAgSWYgeW91XG4vLyBuZXZlciBjYWxsIGNiKCksIHRoZW4geW91J2xsIG5ldmVyIGdldCBhbm90aGVyIGNodW5rLlxuVHJhbnNmb3JtLnByb3RvdHlwZS5fdHJhbnNmb3JtID0gZnVuY3Rpb24gKGNodW5rLCBlbmNvZGluZywgY2IpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdfdHJhbnNmb3JtKCkgaXMgbm90IGltcGxlbWVudGVkJyk7XG59O1xuXG5UcmFuc2Zvcm0ucHJvdG90eXBlLl93cml0ZSA9IGZ1bmN0aW9uIChjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG4gIHZhciB0cyA9IHRoaXMuX3RyYW5zZm9ybVN0YXRlO1xuICB0cy53cml0ZWNiID0gY2I7XG4gIHRzLndyaXRlY2h1bmsgPSBjaHVuaztcbiAgdHMud3JpdGVlbmNvZGluZyA9IGVuY29kaW5nO1xuICBpZiAoIXRzLnRyYW5zZm9ybWluZykge1xuICAgIHZhciBycyA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gICAgaWYgKHRzLm5lZWRUcmFuc2Zvcm0gfHwgcnMubmVlZFJlYWRhYmxlIHx8IHJzLmxlbmd0aCA8IHJzLmhpZ2hXYXRlck1hcmspIHRoaXMuX3JlYWQocnMuaGlnaFdhdGVyTWFyayk7XG4gIH1cbn07XG5cbi8vIERvZXNuJ3QgbWF0dGVyIHdoYXQgdGhlIGFyZ3MgYXJlIGhlcmUuXG4vLyBfdHJhbnNmb3JtIGRvZXMgYWxsIHRoZSB3b3JrLlxuLy8gVGhhdCB3ZSBnb3QgaGVyZSBtZWFucyB0aGF0IHRoZSByZWFkYWJsZSBzaWRlIHdhbnRzIG1vcmUgZGF0YS5cblRyYW5zZm9ybS5wcm90b3R5cGUuX3JlYWQgPSBmdW5jdGlvbiAobikge1xuICB2YXIgdHMgPSB0aGlzLl90cmFuc2Zvcm1TdGF0ZTtcblxuICBpZiAodHMud3JpdGVjaHVuayAhPT0gbnVsbCAmJiB0cy53cml0ZWNiICYmICF0cy50cmFuc2Zvcm1pbmcpIHtcbiAgICB0cy50cmFuc2Zvcm1pbmcgPSB0cnVlO1xuICAgIHRoaXMuX3RyYW5zZm9ybSh0cy53cml0ZWNodW5rLCB0cy53cml0ZWVuY29kaW5nLCB0cy5hZnRlclRyYW5zZm9ybSk7XG4gIH0gZWxzZSB7XG4gICAgLy8gbWFyayB0aGF0IHdlIG5lZWQgYSB0cmFuc2Zvcm0sIHNvIHRoYXQgYW55IGRhdGEgdGhhdCBjb21lcyBpblxuICAgIC8vIHdpbGwgZ2V0IHByb2Nlc3NlZCwgbm93IHRoYXQgd2UndmUgYXNrZWQgZm9yIGl0LlxuICAgIHRzLm5lZWRUcmFuc2Zvcm0gPSB0cnVlO1xuICB9XG59O1xuXG5UcmFuc2Zvcm0ucHJvdG90eXBlLl9kZXN0cm95ID0gZnVuY3Rpb24gKGVyciwgY2IpIHtcbiAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgRHVwbGV4LnByb3RvdHlwZS5fZGVzdHJveS5jYWxsKHRoaXMsIGVyciwgZnVuY3Rpb24gKGVycjIpIHtcbiAgICBjYihlcnIyKTtcbiAgICBfdGhpczIuZW1pdCgnY2xvc2UnKTtcbiAgfSk7XG59O1xuXG5mdW5jdGlvbiBkb25lKHN0cmVhbSwgZXIsIGRhdGEpIHtcbiAgaWYgKGVyKSByZXR1cm4gc3RyZWFtLmVtaXQoJ2Vycm9yJywgZXIpO1xuXG4gIGlmIChkYXRhICE9IG51bGwpIC8vIHNpbmdsZSBlcXVhbHMgY2hlY2sgZm9yIGJvdGggYG51bGxgIGFuZCBgdW5kZWZpbmVkYFxuICAgIHN0cmVhbS5wdXNoKGRhdGEpO1xuXG4gIC8vIGlmIHRoZXJlJ3Mgbm90aGluZyBpbiB0aGUgd3JpdGUgYnVmZmVyLCB0aGVuIHRoYXQgbWVhbnNcbiAgLy8gdGhhdCBub3RoaW5nIG1vcmUgd2lsbCBldmVyIGJlIHByb3ZpZGVkXG4gIGlmIChzdHJlYW0uX3dyaXRhYmxlU3RhdGUubGVuZ3RoKSB0aHJvdyBuZXcgRXJyb3IoJ0NhbGxpbmcgdHJhbnNmb3JtIGRvbmUgd2hlbiB3cy5sZW5ndGggIT0gMCcpO1xuXG4gIGlmIChzdHJlYW0uX3RyYW5zZm9ybVN0YXRlLnRyYW5zZm9ybWluZykgdGhyb3cgbmV3IEVycm9yKCdDYWxsaW5nIHRyYW5zZm9ybSBkb25lIHdoZW4gc3RpbGwgdHJhbnNmb3JtaW5nJyk7XG5cbiAgcmV0dXJuIHN0cmVhbS5wdXNoKG51bGwpO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4vLyBBIGJpdCBzaW1wbGVyIHRoYW4gcmVhZGFibGUgc3RyZWFtcy5cbi8vIEltcGxlbWVudCBhbiBhc3luYyAuX3dyaXRlKGNodW5rLCBlbmNvZGluZywgY2IpLCBhbmQgaXQnbGwgaGFuZGxlIGFsbFxuLy8gdGhlIGRyYWluIGV2ZW50IGVtaXNzaW9uIGFuZCBidWZmZXJpbmcuXG5cbid1c2Ugc3RyaWN0JztcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cblxudmFyIHBuYSA9IHJlcXVpcmUoJ3Byb2Nlc3MtbmV4dGljay1hcmdzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxubW9kdWxlLmV4cG9ydHMgPSBXcml0YWJsZTtcblxuLyogPHJlcGxhY2VtZW50PiAqL1xuZnVuY3Rpb24gV3JpdGVSZXEoY2h1bmssIGVuY29kaW5nLCBjYikge1xuICB0aGlzLmNodW5rID0gY2h1bms7XG4gIHRoaXMuZW5jb2RpbmcgPSBlbmNvZGluZztcbiAgdGhpcy5jYWxsYmFjayA9IGNiO1xuICB0aGlzLm5leHQgPSBudWxsO1xufVxuXG4vLyBJdCBzZWVtcyBhIGxpbmtlZCBsaXN0IGJ1dCBpdCBpcyBub3Rcbi8vIHRoZXJlIHdpbGwgYmUgb25seSAyIG9mIHRoZXNlIGZvciBlYWNoIHN0cmVhbVxuZnVuY3Rpb24gQ29ya2VkUmVxdWVzdChzdGF0ZSkge1xuICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gIHRoaXMubmV4dCA9IG51bGw7XG4gIHRoaXMuZW50cnkgPSBudWxsO1xuICB0aGlzLmZpbmlzaCA9IGZ1bmN0aW9uICgpIHtcbiAgICBvbkNvcmtlZEZpbmlzaChfdGhpcywgc3RhdGUpO1xuICB9O1xufVxuLyogPC9yZXBsYWNlbWVudD4gKi9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBhc3luY1dyaXRlID0gIXByb2Nlc3MuYnJvd3NlciAmJiBbJ3YwLjEwJywgJ3YwLjkuJ10uaW5kZXhPZihwcm9jZXNzLnZlcnNpb24uc2xpY2UoMCwgNSkpID4gLTEgPyBzZXRJbW1lZGlhdGUgOiBwbmEubmV4dFRpY2s7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBEdXBsZXg7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuV3JpdGFibGUuV3JpdGFibGVTdGF0ZSA9IFdyaXRhYmxlU3RhdGU7XG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgdXRpbCA9IHJlcXVpcmUoJ2NvcmUtdXRpbC1pcycpO1xudXRpbC5pbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBpbnRlcm5hbFV0aWwgPSB7XG4gIGRlcHJlY2F0ZTogcmVxdWlyZSgndXRpbC1kZXByZWNhdGUnKVxufTtcbi8qPC9yZXBsYWNlbWVudD4qL1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIFN0cmVhbSA9IHJlcXVpcmUoJy4vaW50ZXJuYWwvc3RyZWFtcy9zdHJlYW0nKTtcbi8qPC9yZXBsYWNlbWVudD4qL1xuXG4vKjxyZXBsYWNlbWVudD4qL1xuXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnc2FmZS1idWZmZXInKS5CdWZmZXI7XG52YXIgT3VyVWludDhBcnJheSA9IGdsb2JhbC5VaW50OEFycmF5IHx8IGZ1bmN0aW9uICgpIHt9O1xuZnVuY3Rpb24gX3VpbnQ4QXJyYXlUb0J1ZmZlcihjaHVuaykge1xuICByZXR1cm4gQnVmZmVyLmZyb20oY2h1bmspO1xufVxuZnVuY3Rpb24gX2lzVWludDhBcnJheShvYmopIHtcbiAgcmV0dXJuIEJ1ZmZlci5pc0J1ZmZlcihvYmopIHx8IG9iaiBpbnN0YW5jZW9mIE91clVpbnQ4QXJyYXk7XG59XG5cbi8qPC9yZXBsYWNlbWVudD4qL1xuXG52YXIgZGVzdHJveUltcGwgPSByZXF1aXJlKCcuL2ludGVybmFsL3N0cmVhbXMvZGVzdHJveScpO1xuXG51dGlsLmluaGVyaXRzKFdyaXRhYmxlLCBTdHJlYW0pO1xuXG5mdW5jdGlvbiBub3AoKSB7fVxuXG5mdW5jdGlvbiBXcml0YWJsZVN0YXRlKG9wdGlvbnMsIHN0cmVhbSkge1xuICBEdXBsZXggPSBEdXBsZXggfHwgcmVxdWlyZSgnLi9fc3RyZWFtX2R1cGxleCcpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIC8vIER1cGxleCBzdHJlYW1zIGFyZSBib3RoIHJlYWRhYmxlIGFuZCB3cml0YWJsZSwgYnV0IHNoYXJlXG4gIC8vIHRoZSBzYW1lIG9wdGlvbnMgb2JqZWN0LlxuICAvLyBIb3dldmVyLCBzb21lIGNhc2VzIHJlcXVpcmUgc2V0dGluZyBvcHRpb25zIHRvIGRpZmZlcmVudFxuICAvLyB2YWx1ZXMgZm9yIHRoZSByZWFkYWJsZSBhbmQgdGhlIHdyaXRhYmxlIHNpZGVzIG9mIHRoZSBkdXBsZXggc3RyZWFtLlxuICAvLyBUaGVzZSBvcHRpb25zIGNhbiBiZSBwcm92aWRlZCBzZXBhcmF0ZWx5IGFzIHJlYWRhYmxlWFhYIGFuZCB3cml0YWJsZVhYWC5cbiAgdmFyIGlzRHVwbGV4ID0gc3RyZWFtIGluc3RhbmNlb2YgRHVwbGV4O1xuXG4gIC8vIG9iamVjdCBzdHJlYW0gZmxhZyB0byBpbmRpY2F0ZSB3aGV0aGVyIG9yIG5vdCB0aGlzIHN0cmVhbVxuICAvLyBjb250YWlucyBidWZmZXJzIG9yIG9iamVjdHMuXG4gIHRoaXMub2JqZWN0TW9kZSA9ICEhb3B0aW9ucy5vYmplY3RNb2RlO1xuXG4gIGlmIChpc0R1cGxleCkgdGhpcy5vYmplY3RNb2RlID0gdGhpcy5vYmplY3RNb2RlIHx8ICEhb3B0aW9ucy53cml0YWJsZU9iamVjdE1vZGU7XG5cbiAgLy8gdGhlIHBvaW50IGF0IHdoaWNoIHdyaXRlKCkgc3RhcnRzIHJldHVybmluZyBmYWxzZVxuICAvLyBOb3RlOiAwIGlzIGEgdmFsaWQgdmFsdWUsIG1lYW5zIHRoYXQgd2UgYWx3YXlzIHJldHVybiBmYWxzZSBpZlxuICAvLyB0aGUgZW50aXJlIGJ1ZmZlciBpcyBub3QgZmx1c2hlZCBpbW1lZGlhdGVseSBvbiB3cml0ZSgpXG4gIHZhciBod20gPSBvcHRpb25zLmhpZ2hXYXRlck1hcms7XG4gIHZhciB3cml0YWJsZUh3bSA9IG9wdGlvbnMud3JpdGFibGVIaWdoV2F0ZXJNYXJrO1xuICB2YXIgZGVmYXVsdEh3bSA9IHRoaXMub2JqZWN0TW9kZSA/IDE2IDogMTYgKiAxMDI0O1xuXG4gIGlmIChod20gfHwgaHdtID09PSAwKSB0aGlzLmhpZ2hXYXRlck1hcmsgPSBod207ZWxzZSBpZiAoaXNEdXBsZXggJiYgKHdyaXRhYmxlSHdtIHx8IHdyaXRhYmxlSHdtID09PSAwKSkgdGhpcy5oaWdoV2F0ZXJNYXJrID0gd3JpdGFibGVId207ZWxzZSB0aGlzLmhpZ2hXYXRlck1hcmsgPSBkZWZhdWx0SHdtO1xuXG4gIC8vIGNhc3QgdG8gaW50cy5cbiAgdGhpcy5oaWdoV2F0ZXJNYXJrID0gTWF0aC5mbG9vcih0aGlzLmhpZ2hXYXRlck1hcmspO1xuXG4gIC8vIGlmIF9maW5hbCBoYXMgYmVlbiBjYWxsZWRcbiAgdGhpcy5maW5hbENhbGxlZCA9IGZhbHNlO1xuXG4gIC8vIGRyYWluIGV2ZW50IGZsYWcuXG4gIHRoaXMubmVlZERyYWluID0gZmFsc2U7XG4gIC8vIGF0IHRoZSBzdGFydCBvZiBjYWxsaW5nIGVuZCgpXG4gIHRoaXMuZW5kaW5nID0gZmFsc2U7XG4gIC8vIHdoZW4gZW5kKCkgaGFzIGJlZW4gY2FsbGVkLCBhbmQgcmV0dXJuZWRcbiAgdGhpcy5lbmRlZCA9IGZhbHNlO1xuICAvLyB3aGVuICdmaW5pc2gnIGlzIGVtaXR0ZWRcbiAgdGhpcy5maW5pc2hlZCA9IGZhbHNlO1xuXG4gIC8vIGhhcyBpdCBiZWVuIGRlc3Ryb3llZFxuICB0aGlzLmRlc3Ryb3llZCA9IGZhbHNlO1xuXG4gIC8vIHNob3VsZCB3ZSBkZWNvZGUgc3RyaW5ncyBpbnRvIGJ1ZmZlcnMgYmVmb3JlIHBhc3NpbmcgdG8gX3dyaXRlP1xuICAvLyB0aGlzIGlzIGhlcmUgc28gdGhhdCBzb21lIG5vZGUtY29yZSBzdHJlYW1zIGNhbiBvcHRpbWl6ZSBzdHJpbmdcbiAgLy8gaGFuZGxpbmcgYXQgYSBsb3dlciBsZXZlbC5cbiAgdmFyIG5vRGVjb2RlID0gb3B0aW9ucy5kZWNvZGVTdHJpbmdzID09PSBmYWxzZTtcbiAgdGhpcy5kZWNvZGVTdHJpbmdzID0gIW5vRGVjb2RlO1xuXG4gIC8vIENyeXB0byBpcyBraW5kIG9mIG9sZCBhbmQgY3J1c3R5LiAgSGlzdG9yaWNhbGx5LCBpdHMgZGVmYXVsdCBzdHJpbmdcbiAgLy8gZW5jb2RpbmcgaXMgJ2JpbmFyeScgc28gd2UgaGF2ZSB0byBtYWtlIHRoaXMgY29uZmlndXJhYmxlLlxuICAvLyBFdmVyeXRoaW5nIGVsc2UgaW4gdGhlIHVuaXZlcnNlIHVzZXMgJ3V0ZjgnLCB0aG91Z2guXG4gIHRoaXMuZGVmYXVsdEVuY29kaW5nID0gb3B0aW9ucy5kZWZhdWx0RW5jb2RpbmcgfHwgJ3V0ZjgnO1xuXG4gIC8vIG5vdCBhbiBhY3R1YWwgYnVmZmVyIHdlIGtlZXAgdHJhY2sgb2YsIGJ1dCBhIG1lYXN1cmVtZW50XG4gIC8vIG9mIGhvdyBtdWNoIHdlJ3JlIHdhaXRpbmcgdG8gZ2V0IHB1c2hlZCB0byBzb21lIHVuZGVybHlpbmdcbiAgLy8gc29ja2V0IG9yIGZpbGUuXG4gIHRoaXMubGVuZ3RoID0gMDtcblxuICAvLyBhIGZsYWcgdG8gc2VlIHdoZW4gd2UncmUgaW4gdGhlIG1pZGRsZSBvZiBhIHdyaXRlLlxuICB0aGlzLndyaXRpbmcgPSBmYWxzZTtcblxuICAvLyB3aGVuIHRydWUgYWxsIHdyaXRlcyB3aWxsIGJlIGJ1ZmZlcmVkIHVudGlsIC51bmNvcmsoKSBjYWxsXG4gIHRoaXMuY29ya2VkID0gMDtcblxuICAvLyBhIGZsYWcgdG8gYmUgYWJsZSB0byB0ZWxsIGlmIHRoZSBvbndyaXRlIGNiIGlzIGNhbGxlZCBpbW1lZGlhdGVseSxcbiAgLy8gb3Igb24gYSBsYXRlciB0aWNrLiAgV2Ugc2V0IHRoaXMgdG8gdHJ1ZSBhdCBmaXJzdCwgYmVjYXVzZSBhbnlcbiAgLy8gYWN0aW9ucyB0aGF0IHNob3VsZG4ndCBoYXBwZW4gdW50aWwgXCJsYXRlclwiIHNob3VsZCBnZW5lcmFsbHkgYWxzb1xuICAvLyBub3QgaGFwcGVuIGJlZm9yZSB0aGUgZmlyc3Qgd3JpdGUgY2FsbC5cbiAgdGhpcy5zeW5jID0gdHJ1ZTtcblxuICAvLyBhIGZsYWcgdG8ga25vdyBpZiB3ZSdyZSBwcm9jZXNzaW5nIHByZXZpb3VzbHkgYnVmZmVyZWQgaXRlbXMsIHdoaWNoXG4gIC8vIG1heSBjYWxsIHRoZSBfd3JpdGUoKSBjYWxsYmFjayBpbiB0aGUgc2FtZSB0aWNrLCBzbyB0aGF0IHdlIGRvbid0XG4gIC8vIGVuZCB1cCBpbiBhbiBvdmVybGFwcGVkIG9ud3JpdGUgc2l0dWF0aW9uLlxuICB0aGlzLmJ1ZmZlclByb2Nlc3NpbmcgPSBmYWxzZTtcblxuICAvLyB0aGUgY2FsbGJhY2sgdGhhdCdzIHBhc3NlZCB0byBfd3JpdGUoY2h1bmssY2IpXG4gIHRoaXMub253cml0ZSA9IGZ1bmN0aW9uIChlcikge1xuICAgIG9ud3JpdGUoc3RyZWFtLCBlcik7XG4gIH07XG5cbiAgLy8gdGhlIGNhbGxiYWNrIHRoYXQgdGhlIHVzZXIgc3VwcGxpZXMgdG8gd3JpdGUoY2h1bmssZW5jb2RpbmcsY2IpXG4gIHRoaXMud3JpdGVjYiA9IG51bGw7XG5cbiAgLy8gdGhlIGFtb3VudCB0aGF0IGlzIGJlaW5nIHdyaXR0ZW4gd2hlbiBfd3JpdGUgaXMgY2FsbGVkLlxuICB0aGlzLndyaXRlbGVuID0gMDtcblxuICB0aGlzLmJ1ZmZlcmVkUmVxdWVzdCA9IG51bGw7XG4gIHRoaXMubGFzdEJ1ZmZlcmVkUmVxdWVzdCA9IG51bGw7XG5cbiAgLy8gbnVtYmVyIG9mIHBlbmRpbmcgdXNlci1zdXBwbGllZCB3cml0ZSBjYWxsYmFja3NcbiAgLy8gdGhpcyBtdXN0IGJlIDAgYmVmb3JlICdmaW5pc2gnIGNhbiBiZSBlbWl0dGVkXG4gIHRoaXMucGVuZGluZ2NiID0gMDtcblxuICAvLyBlbWl0IHByZWZpbmlzaCBpZiB0aGUgb25seSB0aGluZyB3ZSdyZSB3YWl0aW5nIGZvciBpcyBfd3JpdGUgY2JzXG4gIC8vIFRoaXMgaXMgcmVsZXZhbnQgZm9yIHN5bmNocm9ub3VzIFRyYW5zZm9ybSBzdHJlYW1zXG4gIHRoaXMucHJlZmluaXNoZWQgPSBmYWxzZTtcblxuICAvLyBUcnVlIGlmIHRoZSBlcnJvciB3YXMgYWxyZWFkeSBlbWl0dGVkIGFuZCBzaG91bGQgbm90IGJlIHRocm93biBhZ2FpblxuICB0aGlzLmVycm9yRW1pdHRlZCA9IGZhbHNlO1xuXG4gIC8vIGNvdW50IGJ1ZmZlcmVkIHJlcXVlc3RzXG4gIHRoaXMuYnVmZmVyZWRSZXF1ZXN0Q291bnQgPSAwO1xuXG4gIC8vIGFsbG9jYXRlIHRoZSBmaXJzdCBDb3JrZWRSZXF1ZXN0LCB0aGVyZSBpcyBhbHdheXNcbiAgLy8gb25lIGFsbG9jYXRlZCBhbmQgZnJlZSB0byB1c2UsIGFuZCB3ZSBtYWludGFpbiBhdCBtb3N0IHR3b1xuICB0aGlzLmNvcmtlZFJlcXVlc3RzRnJlZSA9IG5ldyBDb3JrZWRSZXF1ZXN0KHRoaXMpO1xufVxuXG5Xcml0YWJsZVN0YXRlLnByb3RvdHlwZS5nZXRCdWZmZXIgPSBmdW5jdGlvbiBnZXRCdWZmZXIoKSB7XG4gIHZhciBjdXJyZW50ID0gdGhpcy5idWZmZXJlZFJlcXVlc3Q7XG4gIHZhciBvdXQgPSBbXTtcbiAgd2hpbGUgKGN1cnJlbnQpIHtcbiAgICBvdXQucHVzaChjdXJyZW50KTtcbiAgICBjdXJyZW50ID0gY3VycmVudC5uZXh0O1xuICB9XG4gIHJldHVybiBvdXQ7XG59O1xuXG4oZnVuY3Rpb24gKCkge1xuICB0cnkge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShXcml0YWJsZVN0YXRlLnByb3RvdHlwZSwgJ2J1ZmZlcicsIHtcbiAgICAgIGdldDogaW50ZXJuYWxVdGlsLmRlcHJlY2F0ZShmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEJ1ZmZlcigpO1xuICAgICAgfSwgJ193cml0YWJsZVN0YXRlLmJ1ZmZlciBpcyBkZXByZWNhdGVkLiBVc2UgX3dyaXRhYmxlU3RhdGUuZ2V0QnVmZmVyICcgKyAnaW5zdGVhZC4nLCAnREVQMDAwMycpXG4gICAgfSk7XG4gIH0gY2F0Y2ggKF8pIHt9XG59KSgpO1xuXG4vLyBUZXN0IF93cml0YWJsZVN0YXRlIGZvciBpbmhlcml0YW5jZSB0byBhY2NvdW50IGZvciBEdXBsZXggc3RyZWFtcyxcbi8vIHdob3NlIHByb3RvdHlwZSBjaGFpbiBvbmx5IHBvaW50cyB0byBSZWFkYWJsZS5cbnZhciByZWFsSGFzSW5zdGFuY2U7XG5pZiAodHlwZW9mIFN5bWJvbCA9PT0gJ2Z1bmN0aW9uJyAmJiBTeW1ib2wuaGFzSW5zdGFuY2UgJiYgdHlwZW9mIEZ1bmN0aW9uLnByb3RvdHlwZVtTeW1ib2wuaGFzSW5zdGFuY2VdID09PSAnZnVuY3Rpb24nKSB7XG4gIHJlYWxIYXNJbnN0YW5jZSA9IEZ1bmN0aW9uLnByb3RvdHlwZVtTeW1ib2wuaGFzSW5zdGFuY2VdO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoV3JpdGFibGUsIFN5bWJvbC5oYXNJbnN0YW5jZSwge1xuICAgIHZhbHVlOiBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgICBpZiAocmVhbEhhc0luc3RhbmNlLmNhbGwodGhpcywgb2JqZWN0KSkgcmV0dXJuIHRydWU7XG4gICAgICBpZiAodGhpcyAhPT0gV3JpdGFibGUpIHJldHVybiBmYWxzZTtcblxuICAgICAgcmV0dXJuIG9iamVjdCAmJiBvYmplY3QuX3dyaXRhYmxlU3RhdGUgaW5zdGFuY2VvZiBXcml0YWJsZVN0YXRlO1xuICAgIH1cbiAgfSk7XG59IGVsc2Uge1xuICByZWFsSGFzSW5zdGFuY2UgPSBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgcmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mIHRoaXM7XG4gIH07XG59XG5cbmZ1bmN0aW9uIFdyaXRhYmxlKG9wdGlvbnMpIHtcbiAgRHVwbGV4ID0gRHVwbGV4IHx8IHJlcXVpcmUoJy4vX3N0cmVhbV9kdXBsZXgnKTtcblxuICAvLyBXcml0YWJsZSBjdG9yIGlzIGFwcGxpZWQgdG8gRHVwbGV4ZXMsIHRvby5cbiAgLy8gYHJlYWxIYXNJbnN0YW5jZWAgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgdXNpbmcgcGxhaW4gYGluc3RhbmNlb2ZgXG4gIC8vIHdvdWxkIHJldHVybiBmYWxzZSwgYXMgbm8gYF93cml0YWJsZVN0YXRlYCBwcm9wZXJ0eSBpcyBhdHRhY2hlZC5cblxuICAvLyBUcnlpbmcgdG8gdXNlIHRoZSBjdXN0b20gYGluc3RhbmNlb2ZgIGZvciBXcml0YWJsZSBoZXJlIHdpbGwgYWxzbyBicmVhayB0aGVcbiAgLy8gTm9kZS5qcyBMYXp5VHJhbnNmb3JtIGltcGxlbWVudGF0aW9uLCB3aGljaCBoYXMgYSBub24tdHJpdmlhbCBnZXR0ZXIgZm9yXG4gIC8vIGBfd3JpdGFibGVTdGF0ZWAgdGhhdCB3b3VsZCBsZWFkIHRvIGluZmluaXRlIHJlY3Vyc2lvbi5cbiAgaWYgKCFyZWFsSGFzSW5zdGFuY2UuY2FsbChXcml0YWJsZSwgdGhpcykgJiYgISh0aGlzIGluc3RhbmNlb2YgRHVwbGV4KSkge1xuICAgIHJldHVybiBuZXcgV3JpdGFibGUob3B0aW9ucyk7XG4gIH1cblxuICB0aGlzLl93cml0YWJsZVN0YXRlID0gbmV3IFdyaXRhYmxlU3RhdGUob3B0aW9ucywgdGhpcyk7XG5cbiAgLy8gbGVnYWN5LlxuICB0aGlzLndyaXRhYmxlID0gdHJ1ZTtcblxuICBpZiAob3B0aW9ucykge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy53cml0ZSA9PT0gJ2Z1bmN0aW9uJykgdGhpcy5fd3JpdGUgPSBvcHRpb25zLndyaXRlO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLndyaXRldiA9PT0gJ2Z1bmN0aW9uJykgdGhpcy5fd3JpdGV2ID0gb3B0aW9ucy53cml0ZXY7XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMuZGVzdHJveSA9PT0gJ2Z1bmN0aW9uJykgdGhpcy5fZGVzdHJveSA9IG9wdGlvbnMuZGVzdHJveTtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5maW5hbCA9PT0gJ2Z1bmN0aW9uJykgdGhpcy5fZmluYWwgPSBvcHRpb25zLmZpbmFsO1xuICB9XG5cbiAgU3RyZWFtLmNhbGwodGhpcyk7XG59XG5cbi8vIE90aGVyd2lzZSBwZW9wbGUgY2FuIHBpcGUgV3JpdGFibGUgc3RyZWFtcywgd2hpY2ggaXMganVzdCB3cm9uZy5cbldyaXRhYmxlLnByb3RvdHlwZS5waXBlID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmVtaXQoJ2Vycm9yJywgbmV3IEVycm9yKCdDYW5ub3QgcGlwZSwgbm90IHJlYWRhYmxlJykpO1xufTtcblxuZnVuY3Rpb24gd3JpdGVBZnRlckVuZChzdHJlYW0sIGNiKSB7XG4gIHZhciBlciA9IG5ldyBFcnJvcignd3JpdGUgYWZ0ZXIgZW5kJyk7XG4gIC8vIFRPRE86IGRlZmVyIGVycm9yIGV2ZW50cyBjb25zaXN0ZW50bHkgZXZlcnl3aGVyZSwgbm90IGp1c3QgdGhlIGNiXG4gIHN0cmVhbS5lbWl0KCdlcnJvcicsIGVyKTtcbiAgcG5hLm5leHRUaWNrKGNiLCBlcik7XG59XG5cbi8vIENoZWNrcyB0aGF0IGEgdXNlci1zdXBwbGllZCBjaHVuayBpcyB2YWxpZCwgZXNwZWNpYWxseSBmb3IgdGhlIHBhcnRpY3VsYXJcbi8vIG1vZGUgdGhlIHN0cmVhbSBpcyBpbi4gQ3VycmVudGx5IHRoaXMgbWVhbnMgdGhhdCBgbnVsbGAgaXMgbmV2ZXIgYWNjZXB0ZWRcbi8vIGFuZCB1bmRlZmluZWQvbm9uLXN0cmluZyB2YWx1ZXMgYXJlIG9ubHkgYWxsb3dlZCBpbiBvYmplY3QgbW9kZS5cbmZ1bmN0aW9uIHZhbGlkQ2h1bmsoc3RyZWFtLCBzdGF0ZSwgY2h1bmssIGNiKSB7XG4gIHZhciB2YWxpZCA9IHRydWU7XG4gIHZhciBlciA9IGZhbHNlO1xuXG4gIGlmIChjaHVuayA9PT0gbnVsbCkge1xuICAgIGVyID0gbmV3IFR5cGVFcnJvcignTWF5IG5vdCB3cml0ZSBudWxsIHZhbHVlcyB0byBzdHJlYW0nKTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgY2h1bmsgIT09ICdzdHJpbmcnICYmIGNodW5rICE9PSB1bmRlZmluZWQgJiYgIXN0YXRlLm9iamVjdE1vZGUpIHtcbiAgICBlciA9IG5ldyBUeXBlRXJyb3IoJ0ludmFsaWQgbm9uLXN0cmluZy9idWZmZXIgY2h1bmsnKTtcbiAgfVxuICBpZiAoZXIpIHtcbiAgICBzdHJlYW0uZW1pdCgnZXJyb3InLCBlcik7XG4gICAgcG5hLm5leHRUaWNrKGNiLCBlcik7XG4gICAgdmFsaWQgPSBmYWxzZTtcbiAgfVxuICByZXR1cm4gdmFsaWQ7XG59XG5cbldyaXRhYmxlLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIChjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3dyaXRhYmxlU3RhdGU7XG4gIHZhciByZXQgPSBmYWxzZTtcbiAgdmFyIGlzQnVmID0gIXN0YXRlLm9iamVjdE1vZGUgJiYgX2lzVWludDhBcnJheShjaHVuayk7XG5cbiAgaWYgKGlzQnVmICYmICFCdWZmZXIuaXNCdWZmZXIoY2h1bmspKSB7XG4gICAgY2h1bmsgPSBfdWludDhBcnJheVRvQnVmZmVyKGNodW5rKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjYiA9IGVuY29kaW5nO1xuICAgIGVuY29kaW5nID0gbnVsbDtcbiAgfVxuXG4gIGlmIChpc0J1ZikgZW5jb2RpbmcgPSAnYnVmZmVyJztlbHNlIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gc3RhdGUuZGVmYXVsdEVuY29kaW5nO1xuXG4gIGlmICh0eXBlb2YgY2IgIT09ICdmdW5jdGlvbicpIGNiID0gbm9wO1xuXG4gIGlmIChzdGF0ZS5lbmRlZCkgd3JpdGVBZnRlckVuZCh0aGlzLCBjYik7ZWxzZSBpZiAoaXNCdWYgfHwgdmFsaWRDaHVuayh0aGlzLCBzdGF0ZSwgY2h1bmssIGNiKSkge1xuICAgIHN0YXRlLnBlbmRpbmdjYisrO1xuICAgIHJldCA9IHdyaXRlT3JCdWZmZXIodGhpcywgc3RhdGUsIGlzQnVmLCBjaHVuaywgZW5jb2RpbmcsIGNiKTtcbiAgfVxuXG4gIHJldHVybiByZXQ7XG59O1xuXG5Xcml0YWJsZS5wcm90b3R5cGUuY29yayA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIHN0YXRlID0gdGhpcy5fd3JpdGFibGVTdGF0ZTtcblxuICBzdGF0ZS5jb3JrZWQrKztcbn07XG5cbldyaXRhYmxlLnByb3RvdHlwZS51bmNvcmsgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3dyaXRhYmxlU3RhdGU7XG5cbiAgaWYgKHN0YXRlLmNvcmtlZCkge1xuICAgIHN0YXRlLmNvcmtlZC0tO1xuXG4gICAgaWYgKCFzdGF0ZS53cml0aW5nICYmICFzdGF0ZS5jb3JrZWQgJiYgIXN0YXRlLmZpbmlzaGVkICYmICFzdGF0ZS5idWZmZXJQcm9jZXNzaW5nICYmIHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdCkgY2xlYXJCdWZmZXIodGhpcywgc3RhdGUpO1xuICB9XG59O1xuXG5Xcml0YWJsZS5wcm90b3R5cGUuc2V0RGVmYXVsdEVuY29kaW5nID0gZnVuY3Rpb24gc2V0RGVmYXVsdEVuY29kaW5nKGVuY29kaW5nKSB7XG4gIC8vIG5vZGU6OlBhcnNlRW5jb2RpbmcoKSByZXF1aXJlcyBsb3dlciBjYXNlLlxuICBpZiAodHlwZW9mIGVuY29kaW5nID09PSAnc3RyaW5nJykgZW5jb2RpbmcgPSBlbmNvZGluZy50b0xvd2VyQ2FzZSgpO1xuICBpZiAoIShbJ2hleCcsICd1dGY4JywgJ3V0Zi04JywgJ2FzY2lpJywgJ2JpbmFyeScsICdiYXNlNjQnLCAndWNzMicsICd1Y3MtMicsICd1dGYxNmxlJywgJ3V0Zi0xNmxlJywgJ3JhdyddLmluZGV4T2YoKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKCkpID4gLTEpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpO1xuICB0aGlzLl93cml0YWJsZVN0YXRlLmRlZmF1bHRFbmNvZGluZyA9IGVuY29kaW5nO1xuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uIGRlY29kZUNodW5rKHN0YXRlLCBjaHVuaywgZW5jb2RpbmcpIHtcbiAgaWYgKCFzdGF0ZS5vYmplY3RNb2RlICYmIHN0YXRlLmRlY29kZVN0cmluZ3MgIT09IGZhbHNlICYmIHR5cGVvZiBjaHVuayA9PT0gJ3N0cmluZycpIHtcbiAgICBjaHVuayA9IEJ1ZmZlci5mcm9tKGNodW5rLCBlbmNvZGluZyk7XG4gIH1cbiAgcmV0dXJuIGNodW5rO1xufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoV3JpdGFibGUucHJvdG90eXBlLCAnd3JpdGFibGVIaWdoV2F0ZXJNYXJrJywge1xuICAvLyBtYWtpbmcgaXQgZXhwbGljaXQgdGhpcyBwcm9wZXJ0eSBpcyBub3QgZW51bWVyYWJsZVxuICAvLyBiZWNhdXNlIG90aGVyd2lzZSBzb21lIHByb3RvdHlwZSBtYW5pcHVsYXRpb24gaW5cbiAgLy8gdXNlcmxhbmQgd2lsbCBmYWlsXG4gIGVudW1lcmFibGU6IGZhbHNlLFxuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fd3JpdGFibGVTdGF0ZS5oaWdoV2F0ZXJNYXJrO1xuICB9XG59KTtcblxuLy8gaWYgd2UncmUgYWxyZWFkeSB3cml0aW5nIHNvbWV0aGluZywgdGhlbiBqdXN0IHB1dCB0aGlzXG4vLyBpbiB0aGUgcXVldWUsIGFuZCB3YWl0IG91ciB0dXJuLiAgT3RoZXJ3aXNlLCBjYWxsIF93cml0ZVxuLy8gSWYgd2UgcmV0dXJuIGZhbHNlLCB0aGVuIHdlIG5lZWQgYSBkcmFpbiBldmVudCwgc28gc2V0IHRoYXQgZmxhZy5cbmZ1bmN0aW9uIHdyaXRlT3JCdWZmZXIoc3RyZWFtLCBzdGF0ZSwgaXNCdWYsIGNodW5rLCBlbmNvZGluZywgY2IpIHtcbiAgaWYgKCFpc0J1Zikge1xuICAgIHZhciBuZXdDaHVuayA9IGRlY29kZUNodW5rKHN0YXRlLCBjaHVuaywgZW5jb2RpbmcpO1xuICAgIGlmIChjaHVuayAhPT0gbmV3Q2h1bmspIHtcbiAgICAgIGlzQnVmID0gdHJ1ZTtcbiAgICAgIGVuY29kaW5nID0gJ2J1ZmZlcic7XG4gICAgICBjaHVuayA9IG5ld0NodW5rO1xuICAgIH1cbiAgfVxuICB2YXIgbGVuID0gc3RhdGUub2JqZWN0TW9kZSA/IDEgOiBjaHVuay5sZW5ndGg7XG5cbiAgc3RhdGUubGVuZ3RoICs9IGxlbjtcblxuICB2YXIgcmV0ID0gc3RhdGUubGVuZ3RoIDwgc3RhdGUuaGlnaFdhdGVyTWFyaztcbiAgLy8gd2UgbXVzdCBlbnN1cmUgdGhhdCBwcmV2aW91cyBuZWVkRHJhaW4gd2lsbCBub3QgYmUgcmVzZXQgdG8gZmFsc2UuXG4gIGlmICghcmV0KSBzdGF0ZS5uZWVkRHJhaW4gPSB0cnVlO1xuXG4gIGlmIChzdGF0ZS53cml0aW5nIHx8IHN0YXRlLmNvcmtlZCkge1xuICAgIHZhciBsYXN0ID0gc3RhdGUubGFzdEJ1ZmZlcmVkUmVxdWVzdDtcbiAgICBzdGF0ZS5sYXN0QnVmZmVyZWRSZXF1ZXN0ID0ge1xuICAgICAgY2h1bms6IGNodW5rLFxuICAgICAgZW5jb2Rpbmc6IGVuY29kaW5nLFxuICAgICAgaXNCdWY6IGlzQnVmLFxuICAgICAgY2FsbGJhY2s6IGNiLFxuICAgICAgbmV4dDogbnVsbFxuICAgIH07XG4gICAgaWYgKGxhc3QpIHtcbiAgICAgIGxhc3QubmV4dCA9IHN0YXRlLmxhc3RCdWZmZXJlZFJlcXVlc3Q7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdCA9IHN0YXRlLmxhc3RCdWZmZXJlZFJlcXVlc3Q7XG4gICAgfVxuICAgIHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdENvdW50ICs9IDE7XG4gIH0gZWxzZSB7XG4gICAgZG9Xcml0ZShzdHJlYW0sIHN0YXRlLCBmYWxzZSwgbGVuLCBjaHVuaywgZW5jb2RpbmcsIGNiKTtcbiAgfVxuXG4gIHJldHVybiByZXQ7XG59XG5cbmZ1bmN0aW9uIGRvV3JpdGUoc3RyZWFtLCBzdGF0ZSwgd3JpdGV2LCBsZW4sIGNodW5rLCBlbmNvZGluZywgY2IpIHtcbiAgc3RhdGUud3JpdGVsZW4gPSBsZW47XG4gIHN0YXRlLndyaXRlY2IgPSBjYjtcbiAgc3RhdGUud3JpdGluZyA9IHRydWU7XG4gIHN0YXRlLnN5bmMgPSB0cnVlO1xuICBpZiAod3JpdGV2KSBzdHJlYW0uX3dyaXRldihjaHVuaywgc3RhdGUub253cml0ZSk7ZWxzZSBzdHJlYW0uX3dyaXRlKGNodW5rLCBlbmNvZGluZywgc3RhdGUub253cml0ZSk7XG4gIHN0YXRlLnN5bmMgPSBmYWxzZTtcbn1cblxuZnVuY3Rpb24gb253cml0ZUVycm9yKHN0cmVhbSwgc3RhdGUsIHN5bmMsIGVyLCBjYikge1xuICAtLXN0YXRlLnBlbmRpbmdjYjtcblxuICBpZiAoc3luYykge1xuICAgIC8vIGRlZmVyIHRoZSBjYWxsYmFjayBpZiB3ZSBhcmUgYmVpbmcgY2FsbGVkIHN5bmNocm9ub3VzbHlcbiAgICAvLyB0byBhdm9pZCBwaWxpbmcgdXAgdGhpbmdzIG9uIHRoZSBzdGFja1xuICAgIHBuYS5uZXh0VGljayhjYiwgZXIpO1xuICAgIC8vIHRoaXMgY2FuIGVtaXQgZmluaXNoLCBhbmQgaXQgd2lsbCBhbHdheXMgaGFwcGVuXG4gICAgLy8gYWZ0ZXIgZXJyb3JcbiAgICBwbmEubmV4dFRpY2soZmluaXNoTWF5YmUsIHN0cmVhbSwgc3RhdGUpO1xuICAgIHN0cmVhbS5fd3JpdGFibGVTdGF0ZS5lcnJvckVtaXR0ZWQgPSB0cnVlO1xuICAgIHN0cmVhbS5lbWl0KCdlcnJvcicsIGVyKTtcbiAgfSBlbHNlIHtcbiAgICAvLyB0aGUgY2FsbGVyIGV4cGVjdCB0aGlzIHRvIGhhcHBlbiBiZWZvcmUgaWZcbiAgICAvLyBpdCBpcyBhc3luY1xuICAgIGNiKGVyKTtcbiAgICBzdHJlYW0uX3dyaXRhYmxlU3RhdGUuZXJyb3JFbWl0dGVkID0gdHJ1ZTtcbiAgICBzdHJlYW0uZW1pdCgnZXJyb3InLCBlcik7XG4gICAgLy8gdGhpcyBjYW4gZW1pdCBmaW5pc2gsIGJ1dCBmaW5pc2ggbXVzdFxuICAgIC8vIGFsd2F5cyBmb2xsb3cgZXJyb3JcbiAgICBmaW5pc2hNYXliZShzdHJlYW0sIHN0YXRlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBvbndyaXRlU3RhdGVVcGRhdGUoc3RhdGUpIHtcbiAgc3RhdGUud3JpdGluZyA9IGZhbHNlO1xuICBzdGF0ZS53cml0ZWNiID0gbnVsbDtcbiAgc3RhdGUubGVuZ3RoIC09IHN0YXRlLndyaXRlbGVuO1xuICBzdGF0ZS53cml0ZWxlbiA9IDA7XG59XG5cbmZ1bmN0aW9uIG9ud3JpdGUoc3RyZWFtLCBlcikge1xuICB2YXIgc3RhdGUgPSBzdHJlYW0uX3dyaXRhYmxlU3RhdGU7XG4gIHZhciBzeW5jID0gc3RhdGUuc3luYztcbiAgdmFyIGNiID0gc3RhdGUud3JpdGVjYjtcblxuICBvbndyaXRlU3RhdGVVcGRhdGUoc3RhdGUpO1xuXG4gIGlmIChlcikgb253cml0ZUVycm9yKHN0cmVhbSwgc3RhdGUsIHN5bmMsIGVyLCBjYik7ZWxzZSB7XG4gICAgLy8gQ2hlY2sgaWYgd2UncmUgYWN0dWFsbHkgcmVhZHkgdG8gZmluaXNoLCBidXQgZG9uJ3QgZW1pdCB5ZXRcbiAgICB2YXIgZmluaXNoZWQgPSBuZWVkRmluaXNoKHN0YXRlKTtcblxuICAgIGlmICghZmluaXNoZWQgJiYgIXN0YXRlLmNvcmtlZCAmJiAhc3RhdGUuYnVmZmVyUHJvY2Vzc2luZyAmJiBzdGF0ZS5idWZmZXJlZFJlcXVlc3QpIHtcbiAgICAgIGNsZWFyQnVmZmVyKHN0cmVhbSwgc3RhdGUpO1xuICAgIH1cblxuICAgIGlmIChzeW5jKSB7XG4gICAgICAvKjxyZXBsYWNlbWVudD4qL1xuICAgICAgYXN5bmNXcml0ZShhZnRlcldyaXRlLCBzdHJlYW0sIHN0YXRlLCBmaW5pc2hlZCwgY2IpO1xuICAgICAgLyo8L3JlcGxhY2VtZW50PiovXG4gICAgfSBlbHNlIHtcbiAgICAgIGFmdGVyV3JpdGUoc3RyZWFtLCBzdGF0ZSwgZmluaXNoZWQsIGNiKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gYWZ0ZXJXcml0ZShzdHJlYW0sIHN0YXRlLCBmaW5pc2hlZCwgY2IpIHtcbiAgaWYgKCFmaW5pc2hlZCkgb253cml0ZURyYWluKHN0cmVhbSwgc3RhdGUpO1xuICBzdGF0ZS5wZW5kaW5nY2ItLTtcbiAgY2IoKTtcbiAgZmluaXNoTWF5YmUoc3RyZWFtLCBzdGF0ZSk7XG59XG5cbi8vIE11c3QgZm9yY2UgY2FsbGJhY2sgdG8gYmUgY2FsbGVkIG9uIG5leHRUaWNrLCBzbyB0aGF0IHdlIGRvbid0XG4vLyBlbWl0ICdkcmFpbicgYmVmb3JlIHRoZSB3cml0ZSgpIGNvbnN1bWVyIGdldHMgdGhlICdmYWxzZScgcmV0dXJuXG4vLyB2YWx1ZSwgYW5kIGhhcyBhIGNoYW5jZSB0byBhdHRhY2ggYSAnZHJhaW4nIGxpc3RlbmVyLlxuZnVuY3Rpb24gb253cml0ZURyYWluKHN0cmVhbSwgc3RhdGUpIHtcbiAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCAmJiBzdGF0ZS5uZWVkRHJhaW4pIHtcbiAgICBzdGF0ZS5uZWVkRHJhaW4gPSBmYWxzZTtcbiAgICBzdHJlYW0uZW1pdCgnZHJhaW4nKTtcbiAgfVxufVxuXG4vLyBpZiB0aGVyZSdzIHNvbWV0aGluZyBpbiB0aGUgYnVmZmVyIHdhaXRpbmcsIHRoZW4gcHJvY2VzcyBpdFxuZnVuY3Rpb24gY2xlYXJCdWZmZXIoc3RyZWFtLCBzdGF0ZSkge1xuICBzdGF0ZS5idWZmZXJQcm9jZXNzaW5nID0gdHJ1ZTtcbiAgdmFyIGVudHJ5ID0gc3RhdGUuYnVmZmVyZWRSZXF1ZXN0O1xuXG4gIGlmIChzdHJlYW0uX3dyaXRldiAmJiBlbnRyeSAmJiBlbnRyeS5uZXh0KSB7XG4gICAgLy8gRmFzdCBjYXNlLCB3cml0ZSBldmVyeXRoaW5nIHVzaW5nIF93cml0ZXYoKVxuICAgIHZhciBsID0gc3RhdGUuYnVmZmVyZWRSZXF1ZXN0Q291bnQ7XG4gICAgdmFyIGJ1ZmZlciA9IG5ldyBBcnJheShsKTtcbiAgICB2YXIgaG9sZGVyID0gc3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlO1xuICAgIGhvbGRlci5lbnRyeSA9IGVudHJ5O1xuXG4gICAgdmFyIGNvdW50ID0gMDtcbiAgICB2YXIgYWxsQnVmZmVycyA9IHRydWU7XG4gICAgd2hpbGUgKGVudHJ5KSB7XG4gICAgICBidWZmZXJbY291bnRdID0gZW50cnk7XG4gICAgICBpZiAoIWVudHJ5LmlzQnVmKSBhbGxCdWZmZXJzID0gZmFsc2U7XG4gICAgICBlbnRyeSA9IGVudHJ5Lm5leHQ7XG4gICAgICBjb3VudCArPSAxO1xuICAgIH1cbiAgICBidWZmZXIuYWxsQnVmZmVycyA9IGFsbEJ1ZmZlcnM7XG5cbiAgICBkb1dyaXRlKHN0cmVhbSwgc3RhdGUsIHRydWUsIHN0YXRlLmxlbmd0aCwgYnVmZmVyLCAnJywgaG9sZGVyLmZpbmlzaCk7XG5cbiAgICAvLyBkb1dyaXRlIGlzIGFsbW9zdCBhbHdheXMgYXN5bmMsIGRlZmVyIHRoZXNlIHRvIHNhdmUgYSBiaXQgb2YgdGltZVxuICAgIC8vIGFzIHRoZSBob3QgcGF0aCBlbmRzIHdpdGggZG9Xcml0ZVxuICAgIHN0YXRlLnBlbmRpbmdjYisrO1xuICAgIHN0YXRlLmxhc3RCdWZmZXJlZFJlcXVlc3QgPSBudWxsO1xuICAgIGlmIChob2xkZXIubmV4dCkge1xuICAgICAgc3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlID0gaG9sZGVyLm5leHQ7XG4gICAgICBob2xkZXIubmV4dCA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXRlLmNvcmtlZFJlcXVlc3RzRnJlZSA9IG5ldyBDb3JrZWRSZXF1ZXN0KHN0YXRlKTtcbiAgICB9XG4gICAgc3RhdGUuYnVmZmVyZWRSZXF1ZXN0Q291bnQgPSAwO1xuICB9IGVsc2Uge1xuICAgIC8vIFNsb3cgY2FzZSwgd3JpdGUgY2h1bmtzIG9uZS1ieS1vbmVcbiAgICB3aGlsZSAoZW50cnkpIHtcbiAgICAgIHZhciBjaHVuayA9IGVudHJ5LmNodW5rO1xuICAgICAgdmFyIGVuY29kaW5nID0gZW50cnkuZW5jb2Rpbmc7XG4gICAgICB2YXIgY2IgPSBlbnRyeS5jYWxsYmFjaztcbiAgICAgIHZhciBsZW4gPSBzdGF0ZS5vYmplY3RNb2RlID8gMSA6IGNodW5rLmxlbmd0aDtcblxuICAgICAgZG9Xcml0ZShzdHJlYW0sIHN0YXRlLCBmYWxzZSwgbGVuLCBjaHVuaywgZW5jb2RpbmcsIGNiKTtcbiAgICAgIGVudHJ5ID0gZW50cnkubmV4dDtcbiAgICAgIHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdENvdW50LS07XG4gICAgICAvLyBpZiB3ZSBkaWRuJ3QgY2FsbCB0aGUgb253cml0ZSBpbW1lZGlhdGVseSwgdGhlblxuICAgICAgLy8gaXQgbWVhbnMgdGhhdCB3ZSBuZWVkIHRvIHdhaXQgdW50aWwgaXQgZG9lcy5cbiAgICAgIC8vIGFsc28sIHRoYXQgbWVhbnMgdGhhdCB0aGUgY2h1bmsgYW5kIGNiIGFyZSBjdXJyZW50bHlcbiAgICAgIC8vIGJlaW5nIHByb2Nlc3NlZCwgc28gbW92ZSB0aGUgYnVmZmVyIGNvdW50ZXIgcGFzdCB0aGVtLlxuICAgICAgaWYgKHN0YXRlLndyaXRpbmcpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVudHJ5ID09PSBudWxsKSBzdGF0ZS5sYXN0QnVmZmVyZWRSZXF1ZXN0ID0gbnVsbDtcbiAgfVxuXG4gIHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdCA9IGVudHJ5O1xuICBzdGF0ZS5idWZmZXJQcm9jZXNzaW5nID0gZmFsc2U7XG59XG5cbldyaXRhYmxlLnByb3RvdHlwZS5fd3JpdGUgPSBmdW5jdGlvbiAoY2h1bmssIGVuY29kaW5nLCBjYikge1xuICBjYihuZXcgRXJyb3IoJ193cml0ZSgpIGlzIG5vdCBpbXBsZW1lbnRlZCcpKTtcbn07XG5cbldyaXRhYmxlLnByb3RvdHlwZS5fd3JpdGV2ID0gbnVsbDtcblxuV3JpdGFibGUucHJvdG90eXBlLmVuZCA9IGZ1bmN0aW9uIChjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3dyaXRhYmxlU3RhdGU7XG5cbiAgaWYgKHR5cGVvZiBjaHVuayA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIGNiID0gY2h1bms7XG4gICAgY2h1bmsgPSBudWxsO1xuICAgIGVuY29kaW5nID0gbnVsbDtcbiAgfSBlbHNlIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjYiA9IGVuY29kaW5nO1xuICAgIGVuY29kaW5nID0gbnVsbDtcbiAgfVxuXG4gIGlmIChjaHVuayAhPT0gbnVsbCAmJiBjaHVuayAhPT0gdW5kZWZpbmVkKSB0aGlzLndyaXRlKGNodW5rLCBlbmNvZGluZyk7XG5cbiAgLy8gLmVuZCgpIGZ1bGx5IHVuY29ya3NcbiAgaWYgKHN0YXRlLmNvcmtlZCkge1xuICAgIHN0YXRlLmNvcmtlZCA9IDE7XG4gICAgdGhpcy51bmNvcmsoKTtcbiAgfVxuXG4gIC8vIGlnbm9yZSB1bm5lY2Vzc2FyeSBlbmQoKSBjYWxscy5cbiAgaWYgKCFzdGF0ZS5lbmRpbmcgJiYgIXN0YXRlLmZpbmlzaGVkKSBlbmRXcml0YWJsZSh0aGlzLCBzdGF0ZSwgY2IpO1xufTtcblxuZnVuY3Rpb24gbmVlZEZpbmlzaChzdGF0ZSkge1xuICByZXR1cm4gc3RhdGUuZW5kaW5nICYmIHN0YXRlLmxlbmd0aCA9PT0gMCAmJiBzdGF0ZS5idWZmZXJlZFJlcXVlc3QgPT09IG51bGwgJiYgIXN0YXRlLmZpbmlzaGVkICYmICFzdGF0ZS53cml0aW5nO1xufVxuZnVuY3Rpb24gY2FsbEZpbmFsKHN0cmVhbSwgc3RhdGUpIHtcbiAgc3RyZWFtLl9maW5hbChmdW5jdGlvbiAoZXJyKSB7XG4gICAgc3RhdGUucGVuZGluZ2NiLS07XG4gICAgaWYgKGVycikge1xuICAgICAgc3RyZWFtLmVtaXQoJ2Vycm9yJywgZXJyKTtcbiAgICB9XG4gICAgc3RhdGUucHJlZmluaXNoZWQgPSB0cnVlO1xuICAgIHN0cmVhbS5lbWl0KCdwcmVmaW5pc2gnKTtcbiAgICBmaW5pc2hNYXliZShzdHJlYW0sIHN0YXRlKTtcbiAgfSk7XG59XG5mdW5jdGlvbiBwcmVmaW5pc2goc3RyZWFtLCBzdGF0ZSkge1xuICBpZiAoIXN0YXRlLnByZWZpbmlzaGVkICYmICFzdGF0ZS5maW5hbENhbGxlZCkge1xuICAgIGlmICh0eXBlb2Ygc3RyZWFtLl9maW5hbCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgc3RhdGUucGVuZGluZ2NiKys7XG4gICAgICBzdGF0ZS5maW5hbENhbGxlZCA9IHRydWU7XG4gICAgICBwbmEubmV4dFRpY2soY2FsbEZpbmFsLCBzdHJlYW0sIHN0YXRlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RhdGUucHJlZmluaXNoZWQgPSB0cnVlO1xuICAgICAgc3RyZWFtLmVtaXQoJ3ByZWZpbmlzaCcpO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBmaW5pc2hNYXliZShzdHJlYW0sIHN0YXRlKSB7XG4gIHZhciBuZWVkID0gbmVlZEZpbmlzaChzdGF0ZSk7XG4gIGlmIChuZWVkKSB7XG4gICAgcHJlZmluaXNoKHN0cmVhbSwgc3RhdGUpO1xuICAgIGlmIChzdGF0ZS5wZW5kaW5nY2IgPT09IDApIHtcbiAgICAgIHN0YXRlLmZpbmlzaGVkID0gdHJ1ZTtcbiAgICAgIHN0cmVhbS5lbWl0KCdmaW5pc2gnKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5lZWQ7XG59XG5cbmZ1bmN0aW9uIGVuZFdyaXRhYmxlKHN0cmVhbSwgc3RhdGUsIGNiKSB7XG4gIHN0YXRlLmVuZGluZyA9IHRydWU7XG4gIGZpbmlzaE1heWJlKHN0cmVhbSwgc3RhdGUpO1xuICBpZiAoY2IpIHtcbiAgICBpZiAoc3RhdGUuZmluaXNoZWQpIHBuYS5uZXh0VGljayhjYik7ZWxzZSBzdHJlYW0ub25jZSgnZmluaXNoJywgY2IpO1xuICB9XG4gIHN0YXRlLmVuZGVkID0gdHJ1ZTtcbiAgc3RyZWFtLndyaXRhYmxlID0gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIG9uQ29ya2VkRmluaXNoKGNvcmtSZXEsIHN0YXRlLCBlcnIpIHtcbiAgdmFyIGVudHJ5ID0gY29ya1JlcS5lbnRyeTtcbiAgY29ya1JlcS5lbnRyeSA9IG51bGw7XG4gIHdoaWxlIChlbnRyeSkge1xuICAgIHZhciBjYiA9IGVudHJ5LmNhbGxiYWNrO1xuICAgIHN0YXRlLnBlbmRpbmdjYi0tO1xuICAgIGNiKGVycik7XG4gICAgZW50cnkgPSBlbnRyeS5uZXh0O1xuICB9XG4gIGlmIChzdGF0ZS5jb3JrZWRSZXF1ZXN0c0ZyZWUpIHtcbiAgICBzdGF0ZS5jb3JrZWRSZXF1ZXN0c0ZyZWUubmV4dCA9IGNvcmtSZXE7XG4gIH0gZWxzZSB7XG4gICAgc3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlID0gY29ya1JlcTtcbiAgfVxufVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoV3JpdGFibGUucHJvdG90eXBlLCAnZGVzdHJveWVkJywge1xuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5fd3JpdGFibGVTdGF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZDtcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAvLyB3ZSBpZ25vcmUgdGhlIHZhbHVlIGlmIHRoZSBzdHJlYW1cbiAgICAvLyBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQgeWV0XG4gICAgaWYgKCF0aGlzLl93cml0YWJsZVN0YXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gYmFja3dhcmQgY29tcGF0aWJpbGl0eSwgdGhlIHVzZXIgaXMgZXhwbGljaXRseVxuICAgIC8vIG1hbmFnaW5nIGRlc3Ryb3llZFxuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZGVzdHJveWVkID0gdmFsdWU7XG4gIH1cbn0pO1xuXG5Xcml0YWJsZS5wcm90b3R5cGUuZGVzdHJveSA9IGRlc3Ryb3lJbXBsLmRlc3Ryb3k7XG5Xcml0YWJsZS5wcm90b3R5cGUuX3VuZGVzdHJveSA9IGRlc3Ryb3lJbXBsLnVuZGVzdHJveTtcbldyaXRhYmxlLnByb3RvdHlwZS5fZGVzdHJveSA9IGZ1bmN0aW9uIChlcnIsIGNiKSB7XG4gIHRoaXMuZW5kKCk7XG4gIGNiKGVycik7XG59OyIsIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyO1xudmFyIHV0aWwgPSByZXF1aXJlKCd1dGlsJyk7XG5cbmZ1bmN0aW9uIGNvcHlCdWZmZXIoc3JjLCB0YXJnZXQsIG9mZnNldCkge1xuICBzcmMuY29weSh0YXJnZXQsIG9mZnNldCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICBmdW5jdGlvbiBCdWZmZXJMaXN0KCkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBCdWZmZXJMaXN0KTtcblxuICAgIHRoaXMuaGVhZCA9IG51bGw7XG4gICAgdGhpcy50YWlsID0gbnVsbDtcbiAgICB0aGlzLmxlbmd0aCA9IDA7XG4gIH1cblxuICBCdWZmZXJMaXN0LnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24gcHVzaCh2KSB7XG4gICAgdmFyIGVudHJ5ID0geyBkYXRhOiB2LCBuZXh0OiBudWxsIH07XG4gICAgaWYgKHRoaXMubGVuZ3RoID4gMCkgdGhpcy50YWlsLm5leHQgPSBlbnRyeTtlbHNlIHRoaXMuaGVhZCA9IGVudHJ5O1xuICAgIHRoaXMudGFpbCA9IGVudHJ5O1xuICAgICsrdGhpcy5sZW5ndGg7XG4gIH07XG5cbiAgQnVmZmVyTGlzdC5wcm90b3R5cGUudW5zaGlmdCA9IGZ1bmN0aW9uIHVuc2hpZnQodikge1xuICAgIHZhciBlbnRyeSA9IHsgZGF0YTogdiwgbmV4dDogdGhpcy5oZWFkIH07XG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSB0aGlzLnRhaWwgPSBlbnRyeTtcbiAgICB0aGlzLmhlYWQgPSBlbnRyeTtcbiAgICArK3RoaXMubGVuZ3RoO1xuICB9O1xuXG4gIEJ1ZmZlckxpc3QucHJvdG90eXBlLnNoaWZ0ID0gZnVuY3Rpb24gc2hpZnQoKSB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgdmFyIHJldCA9IHRoaXMuaGVhZC5kYXRhO1xuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMSkgdGhpcy5oZWFkID0gdGhpcy50YWlsID0gbnVsbDtlbHNlIHRoaXMuaGVhZCA9IHRoaXMuaGVhZC5uZXh0O1xuICAgIC0tdGhpcy5sZW5ndGg7XG4gICAgcmV0dXJuIHJldDtcbiAgfTtcblxuICBCdWZmZXJMaXN0LnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgIHRoaXMuaGVhZCA9IHRoaXMudGFpbCA9IG51bGw7XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuICB9O1xuXG4gIEJ1ZmZlckxpc3QucHJvdG90eXBlLmpvaW4gPSBmdW5jdGlvbiBqb2luKHMpIHtcbiAgICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVybiAnJztcbiAgICB2YXIgcCA9IHRoaXMuaGVhZDtcbiAgICB2YXIgcmV0ID0gJycgKyBwLmRhdGE7XG4gICAgd2hpbGUgKHAgPSBwLm5leHQpIHtcbiAgICAgIHJldCArPSBzICsgcC5kYXRhO1xuICAgIH1yZXR1cm4gcmV0O1xuICB9O1xuXG4gIEJ1ZmZlckxpc3QucHJvdG90eXBlLmNvbmNhdCA9IGZ1bmN0aW9uIGNvbmNhdChuKSB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gQnVmZmVyLmFsbG9jKDApO1xuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHRoaXMuaGVhZC5kYXRhO1xuICAgIHZhciByZXQgPSBCdWZmZXIuYWxsb2NVbnNhZmUobiA+Pj4gMCk7XG4gICAgdmFyIHAgPSB0aGlzLmhlYWQ7XG4gICAgdmFyIGkgPSAwO1xuICAgIHdoaWxlIChwKSB7XG4gICAgICBjb3B5QnVmZmVyKHAuZGF0YSwgcmV0LCBpKTtcbiAgICAgIGkgKz0gcC5kYXRhLmxlbmd0aDtcbiAgICAgIHAgPSBwLm5leHQ7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH07XG5cbiAgcmV0dXJuIEJ1ZmZlckxpc3Q7XG59KCk7XG5cbmlmICh1dGlsICYmIHV0aWwuaW5zcGVjdCAmJiB1dGlsLmluc3BlY3QuY3VzdG9tKSB7XG4gIG1vZHVsZS5leHBvcnRzLnByb3RvdHlwZVt1dGlsLmluc3BlY3QuY3VzdG9tXSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgb2JqID0gdXRpbC5pbnNwZWN0KHsgbGVuZ3RoOiB0aGlzLmxlbmd0aCB9KTtcbiAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lICsgJyAnICsgb2JqO1xuICB9O1xufSIsIid1c2Ugc3RyaWN0JztcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cblxudmFyIHBuYSA9IHJlcXVpcmUoJ3Byb2Nlc3MtbmV4dGljay1hcmdzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLy8gdW5kb2N1bWVudGVkIGNiKCkgQVBJLCBuZWVkZWQgZm9yIGNvcmUsIG5vdCBmb3IgcHVibGljIEFQSVxuZnVuY3Rpb24gZGVzdHJveShlcnIsIGNiKSB7XG4gIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgdmFyIHJlYWRhYmxlRGVzdHJveWVkID0gdGhpcy5fcmVhZGFibGVTdGF0ZSAmJiB0aGlzLl9yZWFkYWJsZVN0YXRlLmRlc3Ryb3llZDtcbiAgdmFyIHdyaXRhYmxlRGVzdHJveWVkID0gdGhpcy5fd3JpdGFibGVTdGF0ZSAmJiB0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZDtcblxuICBpZiAocmVhZGFibGVEZXN0cm95ZWQgfHwgd3JpdGFibGVEZXN0cm95ZWQpIHtcbiAgICBpZiAoY2IpIHtcbiAgICAgIGNiKGVycik7XG4gICAgfSBlbHNlIGlmIChlcnIgJiYgKCF0aGlzLl93cml0YWJsZVN0YXRlIHx8ICF0aGlzLl93cml0YWJsZVN0YXRlLmVycm9yRW1pdHRlZCkpIHtcbiAgICAgIHBuYS5uZXh0VGljayhlbWl0RXJyb3JOVCwgdGhpcywgZXJyKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvLyB3ZSBzZXQgZGVzdHJveWVkIHRvIHRydWUgYmVmb3JlIGZpcmluZyBlcnJvciBjYWxsYmFja3MgaW4gb3JkZXJcbiAgLy8gdG8gbWFrZSBpdCByZS1lbnRyYW5jZSBzYWZlIGluIGNhc2UgZGVzdHJveSgpIGlzIGNhbGxlZCB3aXRoaW4gY2FsbGJhY2tzXG5cbiAgaWYgKHRoaXMuX3JlYWRhYmxlU3RhdGUpIHtcbiAgICB0aGlzLl9yZWFkYWJsZVN0YXRlLmRlc3Ryb3llZCA9IHRydWU7XG4gIH1cblxuICAvLyBpZiB0aGlzIGlzIGEgZHVwbGV4IHN0cmVhbSBtYXJrIHRoZSB3cml0YWJsZSBwYXJ0IGFzIGRlc3Ryb3llZCBhcyB3ZWxsXG4gIGlmICh0aGlzLl93cml0YWJsZVN0YXRlKSB7XG4gICAgdGhpcy5fd3JpdGFibGVTdGF0ZS5kZXN0cm95ZWQgPSB0cnVlO1xuICB9XG5cbiAgdGhpcy5fZGVzdHJveShlcnIgfHwgbnVsbCwgZnVuY3Rpb24gKGVycikge1xuICAgIGlmICghY2IgJiYgZXJyKSB7XG4gICAgICBwbmEubmV4dFRpY2soZW1pdEVycm9yTlQsIF90aGlzLCBlcnIpO1xuICAgICAgaWYgKF90aGlzLl93cml0YWJsZVN0YXRlKSB7XG4gICAgICAgIF90aGlzLl93cml0YWJsZVN0YXRlLmVycm9yRW1pdHRlZCA9IHRydWU7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjYikge1xuICAgICAgY2IoZXJyKTtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiB1bmRlc3Ryb3koKSB7XG4gIGlmICh0aGlzLl9yZWFkYWJsZVN0YXRlKSB7XG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5kZXN0cm95ZWQgPSBmYWxzZTtcbiAgICB0aGlzLl9yZWFkYWJsZVN0YXRlLnJlYWRpbmcgPSBmYWxzZTtcbiAgICB0aGlzLl9yZWFkYWJsZVN0YXRlLmVuZGVkID0gZmFsc2U7XG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5lbmRFbWl0dGVkID0gZmFsc2U7XG4gIH1cblxuICBpZiAodGhpcy5fd3JpdGFibGVTdGF0ZSkge1xuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZGVzdHJveWVkID0gZmFsc2U7XG4gICAgdGhpcy5fd3JpdGFibGVTdGF0ZS5lbmRlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZW5kaW5nID0gZmFsc2U7XG4gICAgdGhpcy5fd3JpdGFibGVTdGF0ZS5maW5pc2hlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZXJyb3JFbWl0dGVkID0gZmFsc2U7XG4gIH1cbn1cblxuZnVuY3Rpb24gZW1pdEVycm9yTlQoc2VsZiwgZXJyKSB7XG4gIHNlbGYuZW1pdCgnZXJyb3InLCBlcnIpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZGVzdHJveTogZGVzdHJveSxcbiAgdW5kZXN0cm95OiB1bmRlc3Ryb3lcbn07IiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCdldmVudHMnKS5FdmVudEVtaXR0ZXI7XG4iLCJleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2xpYi9fc3RyZWFtX3JlYWRhYmxlLmpzJyk7XG5leHBvcnRzLlN0cmVhbSA9IGV4cG9ydHM7XG5leHBvcnRzLlJlYWRhYmxlID0gZXhwb3J0cztcbmV4cG9ydHMuV3JpdGFibGUgPSByZXF1aXJlKCcuL2xpYi9fc3RyZWFtX3dyaXRhYmxlLmpzJyk7XG5leHBvcnRzLkR1cGxleCA9IHJlcXVpcmUoJy4vbGliL19zdHJlYW1fZHVwbGV4LmpzJyk7XG5leHBvcnRzLlRyYW5zZm9ybSA9IHJlcXVpcmUoJy4vbGliL19zdHJlYW1fdHJhbnNmb3JtLmpzJyk7XG5leHBvcnRzLlBhc3NUaHJvdWdoID0gcmVxdWlyZSgnLi9saWIvX3N0cmVhbV9wYXNzdGhyb3VnaC5qcycpO1xuIiwiLyogZXNsaW50LWRpc2FibGUgbm9kZS9uby1kZXByZWNhdGVkLWFwaSAqL1xudmFyIGJ1ZmZlciA9IHJlcXVpcmUoJ2J1ZmZlcicpXG52YXIgQnVmZmVyID0gYnVmZmVyLkJ1ZmZlclxuXG4vLyBhbHRlcm5hdGl2ZSB0byB1c2luZyBPYmplY3Qua2V5cyBmb3Igb2xkIGJyb3dzZXJzXG5mdW5jdGlvbiBjb3B5UHJvcHMgKHNyYywgZHN0KSB7XG4gIGZvciAodmFyIGtleSBpbiBzcmMpIHtcbiAgICBkc3Rba2V5XSA9IHNyY1trZXldXG4gIH1cbn1cbmlmIChCdWZmZXIuZnJvbSAmJiBCdWZmZXIuYWxsb2MgJiYgQnVmZmVyLmFsbG9jVW5zYWZlICYmIEJ1ZmZlci5hbGxvY1Vuc2FmZVNsb3cpIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBidWZmZXJcbn0gZWxzZSB7XG4gIC8vIENvcHkgcHJvcGVydGllcyBmcm9tIHJlcXVpcmUoJ2J1ZmZlcicpXG4gIGNvcHlQcm9wcyhidWZmZXIsIGV4cG9ydHMpXG4gIGV4cG9ydHMuQnVmZmVyID0gU2FmZUJ1ZmZlclxufVxuXG5mdW5jdGlvbiBTYWZlQnVmZmVyIChhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gQnVmZmVyKGFyZywgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKVxufVxuXG4vLyBDb3B5IHN0YXRpYyBtZXRob2RzIGZyb20gQnVmZmVyXG5jb3B5UHJvcHMoQnVmZmVyLCBTYWZlQnVmZmVyKVxuXG5TYWZlQnVmZmVyLmZyb20gPSBmdW5jdGlvbiAoYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBub3QgYmUgYSBudW1iZXInKVxuICB9XG4gIHJldHVybiBCdWZmZXIoYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG59XG5cblNhZmVCdWZmZXIuYWxsb2MgPSBmdW5jdGlvbiAoc2l6ZSwgZmlsbCwgZW5jb2RpbmcpIHtcbiAgaWYgKHR5cGVvZiBzaXplICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBudW1iZXInKVxuICB9XG4gIHZhciBidWYgPSBCdWZmZXIoc2l6ZSlcbiAgaWYgKGZpbGwgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdzdHJpbmcnKSB7XG4gICAgICBidWYuZmlsbChmaWxsLCBlbmNvZGluZylcbiAgICB9IGVsc2Uge1xuICAgICAgYnVmLmZpbGwoZmlsbClcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgYnVmLmZpbGwoMClcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cblNhZmVCdWZmZXIuYWxsb2NVbnNhZmUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICBpZiAodHlwZW9mIHNpemUgIT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIG51bWJlcicpXG4gIH1cbiAgcmV0dXJuIEJ1ZmZlcihzaXplKVxufVxuXG5TYWZlQnVmZmVyLmFsbG9jVW5zYWZlU2xvdyA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIGlmICh0eXBlb2Ygc2l6ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgbnVtYmVyJylcbiAgfVxuICByZXR1cm4gYnVmZmVyLlNsb3dCdWZmZXIoc2l6ZSlcbn1cbiIsInZhciBDbGllbnRSZXF1ZXN0ID0gcmVxdWlyZSgnLi9saWIvcmVxdWVzdCcpXG52YXIgcmVzcG9uc2UgPSByZXF1aXJlKCcuL2xpYi9yZXNwb25zZScpXG52YXIgZXh0ZW5kID0gcmVxdWlyZSgneHRlbmQnKVxudmFyIHN0YXR1c0NvZGVzID0gcmVxdWlyZSgnYnVpbHRpbi1zdGF0dXMtY29kZXMnKVxudmFyIHVybCA9IHJlcXVpcmUoJ3VybCcpXG5cbnZhciBodHRwID0gZXhwb3J0c1xuXG5odHRwLnJlcXVlc3QgPSBmdW5jdGlvbiAob3B0cywgY2IpIHtcblx0aWYgKHR5cGVvZiBvcHRzID09PSAnc3RyaW5nJylcblx0XHRvcHRzID0gdXJsLnBhcnNlKG9wdHMpXG5cdGVsc2Vcblx0XHRvcHRzID0gZXh0ZW5kKG9wdHMpXG5cblx0Ly8gTm9ybWFsbHksIHRoZSBwYWdlIGlzIGxvYWRlZCBmcm9tIGh0dHAgb3IgaHR0cHMsIHNvIG5vdCBzcGVjaWZ5aW5nIGEgcHJvdG9jb2xcblx0Ly8gd2lsbCByZXN1bHQgaW4gYSAodmFsaWQpIHByb3RvY29sLXJlbGF0aXZlIHVybC4gSG93ZXZlciwgdGhpcyB3b24ndCB3b3JrIGlmXG5cdC8vIHRoZSBwcm90b2NvbCBpcyBzb21ldGhpbmcgZWxzZSwgbGlrZSAnZmlsZTonXG5cdHZhciBkZWZhdWx0UHJvdG9jb2wgPSBnbG9iYWwubG9jYXRpb24ucHJvdG9jb2wuc2VhcmNoKC9eaHR0cHM/OiQvKSA9PT0gLTEgPyAnaHR0cDonIDogJydcblxuXHR2YXIgcHJvdG9jb2wgPSBvcHRzLnByb3RvY29sIHx8IGRlZmF1bHRQcm90b2NvbFxuXHR2YXIgaG9zdCA9IG9wdHMuaG9zdG5hbWUgfHwgb3B0cy5ob3N0XG5cdHZhciBwb3J0ID0gb3B0cy5wb3J0XG5cdHZhciBwYXRoID0gb3B0cy5wYXRoIHx8ICcvJ1xuXG5cdC8vIE5lY2Vzc2FyeSBmb3IgSVB2NiBhZGRyZXNzZXNcblx0aWYgKGhvc3QgJiYgaG9zdC5pbmRleE9mKCc6JykgIT09IC0xKVxuXHRcdGhvc3QgPSAnWycgKyBob3N0ICsgJ10nXG5cblx0Ly8gVGhpcyBtYXkgYmUgYSByZWxhdGl2ZSB1cmwuIFRoZSBicm93c2VyIHNob3VsZCBhbHdheXMgYmUgYWJsZSB0byBpbnRlcnByZXQgaXQgY29ycmVjdGx5LlxuXHRvcHRzLnVybCA9IChob3N0ID8gKHByb3RvY29sICsgJy8vJyArIGhvc3QpIDogJycpICsgKHBvcnQgPyAnOicgKyBwb3J0IDogJycpICsgcGF0aFxuXHRvcHRzLm1ldGhvZCA9IChvcHRzLm1ldGhvZCB8fCAnR0VUJykudG9VcHBlckNhc2UoKVxuXHRvcHRzLmhlYWRlcnMgPSBvcHRzLmhlYWRlcnMgfHwge31cblxuXHQvLyBBbHNvIHZhbGlkIG9wdHMuYXV0aCwgb3B0cy5tb2RlXG5cblx0dmFyIHJlcSA9IG5ldyBDbGllbnRSZXF1ZXN0KG9wdHMpXG5cdGlmIChjYilcblx0XHRyZXEub24oJ3Jlc3BvbnNlJywgY2IpXG5cdHJldHVybiByZXFcbn1cblxuaHR0cC5nZXQgPSBmdW5jdGlvbiBnZXQgKG9wdHMsIGNiKSB7XG5cdHZhciByZXEgPSBodHRwLnJlcXVlc3Qob3B0cywgY2IpXG5cdHJlcS5lbmQoKVxuXHRyZXR1cm4gcmVxXG59XG5cbmh0dHAuQ2xpZW50UmVxdWVzdCA9IENsaWVudFJlcXVlc3Rcbmh0dHAuSW5jb21pbmdNZXNzYWdlID0gcmVzcG9uc2UuSW5jb21pbmdNZXNzYWdlXG5cbmh0dHAuQWdlbnQgPSBmdW5jdGlvbiAoKSB7fVxuaHR0cC5BZ2VudC5kZWZhdWx0TWF4U29ja2V0cyA9IDRcblxuaHR0cC5nbG9iYWxBZ2VudCA9IG5ldyBodHRwLkFnZW50KClcblxuaHR0cC5TVEFUVVNfQ09ERVMgPSBzdGF0dXNDb2Rlc1xuXG5odHRwLk1FVEhPRFMgPSBbXG5cdCdDSEVDS09VVCcsXG5cdCdDT05ORUNUJyxcblx0J0NPUFknLFxuXHQnREVMRVRFJyxcblx0J0dFVCcsXG5cdCdIRUFEJyxcblx0J0xPQ0snLFxuXHQnTS1TRUFSQ0gnLFxuXHQnTUVSR0UnLFxuXHQnTUtBQ1RJVklUWScsXG5cdCdNS0NPTCcsXG5cdCdNT1ZFJyxcblx0J05PVElGWScsXG5cdCdPUFRJT05TJyxcblx0J1BBVENIJyxcblx0J1BPU1QnLFxuXHQnUFJPUEZJTkQnLFxuXHQnUFJPUFBBVENIJyxcblx0J1BVUkdFJyxcblx0J1BVVCcsXG5cdCdSRVBPUlQnLFxuXHQnU0VBUkNIJyxcblx0J1NVQlNDUklCRScsXG5cdCdUUkFDRScsXG5cdCdVTkxPQ0snLFxuXHQnVU5TVUJTQ1JJQkUnXG5dIiwiZXhwb3J0cy5mZXRjaCA9IGlzRnVuY3Rpb24oZ2xvYmFsLmZldGNoKSAmJiBpc0Z1bmN0aW9uKGdsb2JhbC5SZWFkYWJsZVN0cmVhbSlcblxuZXhwb3J0cy53cml0YWJsZVN0cmVhbSA9IGlzRnVuY3Rpb24oZ2xvYmFsLldyaXRhYmxlU3RyZWFtKVxuXG5leHBvcnRzLmFib3J0Q29udHJvbGxlciA9IGlzRnVuY3Rpb24oZ2xvYmFsLkFib3J0Q29udHJvbGxlcilcblxuZXhwb3J0cy5ibG9iQ29uc3RydWN0b3IgPSBmYWxzZVxudHJ5IHtcblx0bmV3IEJsb2IoW25ldyBBcnJheUJ1ZmZlcigxKV0pXG5cdGV4cG9ydHMuYmxvYkNvbnN0cnVjdG9yID0gdHJ1ZVxufSBjYXRjaCAoZSkge31cblxuLy8gVGhlIHhociByZXF1ZXN0IHRvIGV4YW1wbGUuY29tIG1heSB2aW9sYXRlIHNvbWUgcmVzdHJpY3RpdmUgQ1NQIGNvbmZpZ3VyYXRpb25zLFxuLy8gc28gaWYgd2UncmUgcnVubmluZyBpbiBhIGJyb3dzZXIgdGhhdCBzdXBwb3J0cyBgZmV0Y2hgLCBhdm9pZCBjYWxsaW5nIGdldFhIUigpXG4vLyBhbmQgYXNzdW1lIHN1cHBvcnQgZm9yIGNlcnRhaW4gZmVhdHVyZXMgYmVsb3cuXG52YXIgeGhyXG5mdW5jdGlvbiBnZXRYSFIgKCkge1xuXHQvLyBDYWNoZSB0aGUgeGhyIHZhbHVlXG5cdGlmICh4aHIgIT09IHVuZGVmaW5lZCkgcmV0dXJuIHhoclxuXG5cdGlmIChnbG9iYWwuWE1MSHR0cFJlcXVlc3QpIHtcblx0XHR4aHIgPSBuZXcgZ2xvYmFsLlhNTEh0dHBSZXF1ZXN0KClcblx0XHQvLyBJZiBYRG9tYWluUmVxdWVzdCBpcyBhdmFpbGFibGUgKGllIG9ubHksIHdoZXJlIHhociBtaWdodCBub3Qgd29ya1xuXHRcdC8vIGNyb3NzIGRvbWFpbiksIHVzZSB0aGUgcGFnZSBsb2NhdGlvbi4gT3RoZXJ3aXNlIHVzZSBleGFtcGxlLmNvbVxuXHRcdC8vIE5vdGU6IHRoaXMgZG9lc24ndCBhY3R1YWxseSBtYWtlIGFuIGh0dHAgcmVxdWVzdC5cblx0XHR0cnkge1xuXHRcdFx0eGhyLm9wZW4oJ0dFVCcsIGdsb2JhbC5YRG9tYWluUmVxdWVzdCA/ICcvJyA6ICdodHRwczovL2V4YW1wbGUuY29tJylcblx0XHR9IGNhdGNoKGUpIHtcblx0XHRcdHhociA9IG51bGxcblx0XHR9XG5cdH0gZWxzZSB7XG5cdFx0Ly8gU2VydmljZSB3b3JrZXJzIGRvbid0IGhhdmUgWEhSXG5cdFx0eGhyID0gbnVsbFxuXHR9XG5cdHJldHVybiB4aHJcbn1cblxuZnVuY3Rpb24gY2hlY2tUeXBlU3VwcG9ydCAodHlwZSkge1xuXHR2YXIgeGhyID0gZ2V0WEhSKClcblx0aWYgKCF4aHIpIHJldHVybiBmYWxzZVxuXHR0cnkge1xuXHRcdHhoci5yZXNwb25zZVR5cGUgPSB0eXBlXG5cdFx0cmV0dXJuIHhoci5yZXNwb25zZVR5cGUgPT09IHR5cGVcblx0fSBjYXRjaCAoZSkge31cblx0cmV0dXJuIGZhbHNlXG59XG5cbi8vIEZvciBzb21lIHN0cmFuZ2UgcmVhc29uLCBTYWZhcmkgNy4wIHJlcG9ydHMgdHlwZW9mIGdsb2JhbC5BcnJheUJ1ZmZlciA9PT0gJ29iamVjdCcuXG4vLyBTYWZhcmkgNy4xIGFwcGVhcnMgdG8gaGF2ZSBmaXhlZCB0aGlzIGJ1Zy5cbnZhciBoYXZlQXJyYXlCdWZmZXIgPSB0eXBlb2YgZ2xvYmFsLkFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJ1xudmFyIGhhdmVTbGljZSA9IGhhdmVBcnJheUJ1ZmZlciAmJiBpc0Z1bmN0aW9uKGdsb2JhbC5BcnJheUJ1ZmZlci5wcm90b3R5cGUuc2xpY2UpXG5cbi8vIElmIGZldGNoIGlzIHN1cHBvcnRlZCwgdGhlbiBhcnJheWJ1ZmZlciB3aWxsIGJlIHN1cHBvcnRlZCB0b28uIFNraXAgY2FsbGluZ1xuLy8gY2hlY2tUeXBlU3VwcG9ydCgpLCBzaW5jZSB0aGF0IGNhbGxzIGdldFhIUigpLlxuZXhwb3J0cy5hcnJheWJ1ZmZlciA9IGV4cG9ydHMuZmV0Y2ggfHwgKGhhdmVBcnJheUJ1ZmZlciAmJiBjaGVja1R5cGVTdXBwb3J0KCdhcnJheWJ1ZmZlcicpKVxuXG4vLyBUaGVzZSBuZXh0IHR3byB0ZXN0cyB1bmF2b2lkYWJseSBzaG93IHdhcm5pbmdzIGluIENocm9tZS4gU2luY2UgZmV0Y2ggd2lsbCBhbHdheXNcbi8vIGJlIHVzZWQgaWYgaXQncyBhdmFpbGFibGUsIGp1c3QgcmV0dXJuIGZhbHNlIGZvciB0aGVzZSB0byBhdm9pZCB0aGUgd2FybmluZ3MuXG5leHBvcnRzLm1zc3RyZWFtID0gIWV4cG9ydHMuZmV0Y2ggJiYgaGF2ZVNsaWNlICYmIGNoZWNrVHlwZVN1cHBvcnQoJ21zLXN0cmVhbScpXG5leHBvcnRzLm1vemNodW5rZWRhcnJheWJ1ZmZlciA9ICFleHBvcnRzLmZldGNoICYmIGhhdmVBcnJheUJ1ZmZlciAmJlxuXHRjaGVja1R5cGVTdXBwb3J0KCdtb3otY2h1bmtlZC1hcnJheWJ1ZmZlcicpXG5cbi8vIElmIGZldGNoIGlzIHN1cHBvcnRlZCwgdGhlbiBvdmVycmlkZU1pbWVUeXBlIHdpbGwgYmUgc3VwcG9ydGVkIHRvby4gU2tpcCBjYWxsaW5nXG4vLyBnZXRYSFIoKS5cbmV4cG9ydHMub3ZlcnJpZGVNaW1lVHlwZSA9IGV4cG9ydHMuZmV0Y2ggfHwgKGdldFhIUigpID8gaXNGdW5jdGlvbihnZXRYSFIoKS5vdmVycmlkZU1pbWVUeXBlKSA6IGZhbHNlKVxuXG5leHBvcnRzLnZiQXJyYXkgPSBpc0Z1bmN0aW9uKGdsb2JhbC5WQkFycmF5KVxuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uICh2YWx1ZSkge1xuXHRyZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nXG59XG5cbnhociA9IG51bGwgLy8gSGVscCBnY1xuIiwidmFyIGNhcGFiaWxpdHkgPSByZXF1aXJlKCcuL2NhcGFiaWxpdHknKVxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIHJlc3BvbnNlID0gcmVxdWlyZSgnLi9yZXNwb25zZScpXG52YXIgc3RyZWFtID0gcmVxdWlyZSgncmVhZGFibGUtc3RyZWFtJylcbnZhciB0b0FycmF5QnVmZmVyID0gcmVxdWlyZSgndG8tYXJyYXlidWZmZXInKVxuXG52YXIgSW5jb21pbmdNZXNzYWdlID0gcmVzcG9uc2UuSW5jb21pbmdNZXNzYWdlXG52YXIgclN0YXRlcyA9IHJlc3BvbnNlLnJlYWR5U3RhdGVzXG5cbmZ1bmN0aW9uIGRlY2lkZU1vZGUgKHByZWZlckJpbmFyeSwgdXNlRmV0Y2gpIHtcblx0aWYgKGNhcGFiaWxpdHkuZmV0Y2ggJiYgdXNlRmV0Y2gpIHtcblx0XHRyZXR1cm4gJ2ZldGNoJ1xuXHR9IGVsc2UgaWYgKGNhcGFiaWxpdHkubW96Y2h1bmtlZGFycmF5YnVmZmVyKSB7XG5cdFx0cmV0dXJuICdtb3otY2h1bmtlZC1hcnJheWJ1ZmZlcidcblx0fSBlbHNlIGlmIChjYXBhYmlsaXR5Lm1zc3RyZWFtKSB7XG5cdFx0cmV0dXJuICdtcy1zdHJlYW0nXG5cdH0gZWxzZSBpZiAoY2FwYWJpbGl0eS5hcnJheWJ1ZmZlciAmJiBwcmVmZXJCaW5hcnkpIHtcblx0XHRyZXR1cm4gJ2FycmF5YnVmZmVyJ1xuXHR9IGVsc2UgaWYgKGNhcGFiaWxpdHkudmJBcnJheSAmJiBwcmVmZXJCaW5hcnkpIHtcblx0XHRyZXR1cm4gJ3RleHQ6dmJhcnJheSdcblx0fSBlbHNlIHtcblx0XHRyZXR1cm4gJ3RleHQnXG5cdH1cbn1cblxudmFyIENsaWVudFJlcXVlc3QgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvcHRzKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXHRzdHJlYW0uV3JpdGFibGUuY2FsbChzZWxmKVxuXG5cdHNlbGYuX29wdHMgPSBvcHRzXG5cdHNlbGYuX2JvZHkgPSBbXVxuXHRzZWxmLl9oZWFkZXJzID0ge31cblx0aWYgKG9wdHMuYXV0aClcblx0XHRzZWxmLnNldEhlYWRlcignQXV0aG9yaXphdGlvbicsICdCYXNpYyAnICsgbmV3IEJ1ZmZlcihvcHRzLmF1dGgpLnRvU3RyaW5nKCdiYXNlNjQnKSlcblx0T2JqZWN0LmtleXMob3B0cy5oZWFkZXJzKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG5cdFx0c2VsZi5zZXRIZWFkZXIobmFtZSwgb3B0cy5oZWFkZXJzW25hbWVdKVxuXHR9KVxuXG5cdHZhciBwcmVmZXJCaW5hcnlcblx0dmFyIHVzZUZldGNoID0gdHJ1ZVxuXHRpZiAob3B0cy5tb2RlID09PSAnZGlzYWJsZS1mZXRjaCcgfHwgKCdyZXF1ZXN0VGltZW91dCcgaW4gb3B0cyAmJiAhY2FwYWJpbGl0eS5hYm9ydENvbnRyb2xsZXIpKSB7XG5cdFx0Ly8gSWYgdGhlIHVzZSBvZiBYSFIgc2hvdWxkIGJlIHByZWZlcnJlZC4gTm90IHR5cGljYWxseSBuZWVkZWQuXG5cdFx0dXNlRmV0Y2ggPSBmYWxzZVxuXHRcdHByZWZlckJpbmFyeSA9IHRydWVcblx0fSBlbHNlIGlmIChvcHRzLm1vZGUgPT09ICdwcmVmZXItc3RyZWFtaW5nJykge1xuXHRcdC8vIElmIHN0cmVhbWluZyBpcyBhIGhpZ2ggcHJpb3JpdHkgYnV0IGJpbmFyeSBjb21wYXRpYmlsaXR5IGFuZFxuXHRcdC8vIHRoZSBhY2N1cmFjeSBvZiB0aGUgJ2NvbnRlbnQtdHlwZScgaGVhZGVyIGFyZW4ndFxuXHRcdHByZWZlckJpbmFyeSA9IGZhbHNlXG5cdH0gZWxzZSBpZiAob3B0cy5tb2RlID09PSAnYWxsb3ctd3JvbmctY29udGVudC10eXBlJykge1xuXHRcdC8vIElmIHN0cmVhbWluZyBpcyBtb3JlIGltcG9ydGFudCB0aGFuIHByZXNlcnZpbmcgdGhlICdjb250ZW50LXR5cGUnIGhlYWRlclxuXHRcdHByZWZlckJpbmFyeSA9ICFjYXBhYmlsaXR5Lm92ZXJyaWRlTWltZVR5cGVcblx0fSBlbHNlIGlmICghb3B0cy5tb2RlIHx8IG9wdHMubW9kZSA9PT0gJ2RlZmF1bHQnIHx8IG9wdHMubW9kZSA9PT0gJ3ByZWZlci1mYXN0Jykge1xuXHRcdC8vIFVzZSBiaW5hcnkgaWYgdGV4dCBzdHJlYW1pbmcgbWF5IGNvcnJ1cHQgZGF0YSBvciB0aGUgY29udGVudC10eXBlIGhlYWRlciwgb3IgZm9yIHNwZWVkXG5cdFx0cHJlZmVyQmluYXJ5ID0gdHJ1ZVxuXHR9IGVsc2Uge1xuXHRcdHRocm93IG5ldyBFcnJvcignSW52YWxpZCB2YWx1ZSBmb3Igb3B0cy5tb2RlJylcblx0fVxuXHRzZWxmLl9tb2RlID0gZGVjaWRlTW9kZShwcmVmZXJCaW5hcnksIHVzZUZldGNoKVxuXG5cdHNlbGYub24oJ2ZpbmlzaCcsIGZ1bmN0aW9uICgpIHtcblx0XHRzZWxmLl9vbkZpbmlzaCgpXG5cdH0pXG59XG5cbmluaGVyaXRzKENsaWVudFJlcXVlc3QsIHN0cmVhbS5Xcml0YWJsZSlcblxuQ2xpZW50UmVxdWVzdC5wcm90b3R5cGUuc2V0SGVhZGVyID0gZnVuY3Rpb24gKG5hbWUsIHZhbHVlKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXHR2YXIgbG93ZXJOYW1lID0gbmFtZS50b0xvd2VyQ2FzZSgpXG5cdC8vIFRoaXMgY2hlY2sgaXMgbm90IG5lY2Vzc2FyeSwgYnV0IGl0IHByZXZlbnRzIHdhcm5pbmdzIGZyb20gYnJvd3NlcnMgYWJvdXQgc2V0dGluZyB1bnNhZmVcblx0Ly8gaGVhZGVycy4gVG8gYmUgaG9uZXN0IEknbSBub3QgZW50aXJlbHkgc3VyZSBoaWRpbmcgdGhlc2Ugd2FybmluZ3MgaXMgYSBnb29kIHRoaW5nLCBidXRcblx0Ly8gaHR0cC1icm93c2VyaWZ5IGRpZCBpdCwgc28gSSB3aWxsIHRvby5cblx0aWYgKHVuc2FmZUhlYWRlcnMuaW5kZXhPZihsb3dlck5hbWUpICE9PSAtMSlcblx0XHRyZXR1cm5cblxuXHRzZWxmLl9oZWFkZXJzW2xvd2VyTmFtZV0gPSB7XG5cdFx0bmFtZTogbmFtZSxcblx0XHR2YWx1ZTogdmFsdWVcblx0fVxufVxuXG5DbGllbnRSZXF1ZXN0LnByb3RvdHlwZS5nZXRIZWFkZXIgPSBmdW5jdGlvbiAobmFtZSkge1xuXHR2YXIgaGVhZGVyID0gdGhpcy5faGVhZGVyc1tuYW1lLnRvTG93ZXJDYXNlKCldXG5cdGlmIChoZWFkZXIpXG5cdFx0cmV0dXJuIGhlYWRlci52YWx1ZVxuXHRyZXR1cm4gbnVsbFxufVxuXG5DbGllbnRSZXF1ZXN0LnByb3RvdHlwZS5yZW1vdmVIZWFkZXIgPSBmdW5jdGlvbiAobmFtZSkge1xuXHR2YXIgc2VsZiA9IHRoaXNcblx0ZGVsZXRlIHNlbGYuX2hlYWRlcnNbbmFtZS50b0xvd2VyQ2FzZSgpXVxufVxuXG5DbGllbnRSZXF1ZXN0LnByb3RvdHlwZS5fb25GaW5pc2ggPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXG5cdGlmIChzZWxmLl9kZXN0cm95ZWQpXG5cdFx0cmV0dXJuXG5cdHZhciBvcHRzID0gc2VsZi5fb3B0c1xuXG5cdHZhciBoZWFkZXJzT2JqID0gc2VsZi5faGVhZGVyc1xuXHR2YXIgYm9keSA9IG51bGxcblx0aWYgKG9wdHMubWV0aG9kICE9PSAnR0VUJyAmJiBvcHRzLm1ldGhvZCAhPT0gJ0hFQUQnKSB7XG5cdFx0aWYgKGNhcGFiaWxpdHkuYXJyYXlidWZmZXIpIHtcblx0XHRcdGJvZHkgPSB0b0FycmF5QnVmZmVyKEJ1ZmZlci5jb25jYXQoc2VsZi5fYm9keSkpXG5cdFx0fSBlbHNlIGlmIChjYXBhYmlsaXR5LmJsb2JDb25zdHJ1Y3Rvcikge1xuXHRcdFx0Ym9keSA9IG5ldyBnbG9iYWwuQmxvYihzZWxmLl9ib2R5Lm1hcChmdW5jdGlvbiAoYnVmZmVyKSB7XG5cdFx0XHRcdHJldHVybiB0b0FycmF5QnVmZmVyKGJ1ZmZlcilcblx0XHRcdH0pLCB7XG5cdFx0XHRcdHR5cGU6IChoZWFkZXJzT2JqWydjb250ZW50LXR5cGUnXSB8fCB7fSkudmFsdWUgfHwgJydcblx0XHRcdH0pXG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIGdldCB1dGY4IHN0cmluZ1xuXHRcdFx0Ym9keSA9IEJ1ZmZlci5jb25jYXQoc2VsZi5fYm9keSkudG9TdHJpbmcoKVxuXHRcdH1cblx0fVxuXG5cdC8vIGNyZWF0ZSBmbGF0dGVuZWQgbGlzdCBvZiBoZWFkZXJzXG5cdHZhciBoZWFkZXJzTGlzdCA9IFtdXG5cdE9iamVjdC5rZXlzKGhlYWRlcnNPYmopLmZvckVhY2goZnVuY3Rpb24gKGtleU5hbWUpIHtcblx0XHR2YXIgbmFtZSA9IGhlYWRlcnNPYmpba2V5TmFtZV0ubmFtZVxuXHRcdHZhciB2YWx1ZSA9IGhlYWRlcnNPYmpba2V5TmFtZV0udmFsdWVcblx0XHRpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcblx0XHRcdHZhbHVlLmZvckVhY2goZnVuY3Rpb24gKHYpIHtcblx0XHRcdFx0aGVhZGVyc0xpc3QucHVzaChbbmFtZSwgdl0pXG5cdFx0XHR9KVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRoZWFkZXJzTGlzdC5wdXNoKFtuYW1lLCB2YWx1ZV0pXG5cdFx0fVxuXHR9KVxuXG5cdGlmIChzZWxmLl9tb2RlID09PSAnZmV0Y2gnKSB7XG5cdFx0dmFyIHNpZ25hbCA9IG51bGxcblx0XHRpZiAoY2FwYWJpbGl0eS5hYm9ydENvbnRyb2xsZXIpIHtcblx0XHRcdHZhciBjb250cm9sbGVyID0gbmV3IEFib3J0Q29udHJvbGxlcigpXG5cdFx0XHRzaWduYWwgPSBjb250cm9sbGVyLnNpZ25hbFxuXHRcdFx0c2VsZi5fZmV0Y2hBYm9ydENvbnRyb2xsZXIgPSBjb250cm9sbGVyXG5cblx0XHRcdGlmICgncmVxdWVzdFRpbWVvdXQnIGluIG9wdHMgJiYgb3B0cy5yZXF1ZXN0VGltZW91dCAhPT0gMCkge1xuXHRcdFx0XHRnbG9iYWwuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0c2VsZi5lbWl0KCdyZXF1ZXN0VGltZW91dCcpXG5cdFx0XHRcdFx0aWYgKHNlbGYuX2ZldGNoQWJvcnRDb250cm9sbGVyKVxuXHRcdFx0XHRcdFx0c2VsZi5fZmV0Y2hBYm9ydENvbnRyb2xsZXIuYWJvcnQoKVxuXHRcdFx0XHR9LCBvcHRzLnJlcXVlc3RUaW1lb3V0KVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGdsb2JhbC5mZXRjaChzZWxmLl9vcHRzLnVybCwge1xuXHRcdFx0bWV0aG9kOiBzZWxmLl9vcHRzLm1ldGhvZCxcblx0XHRcdGhlYWRlcnM6IGhlYWRlcnNMaXN0LFxuXHRcdFx0Ym9keTogYm9keSB8fCB1bmRlZmluZWQsXG5cdFx0XHRtb2RlOiAnY29ycycsXG5cdFx0XHRjcmVkZW50aWFsczogb3B0cy53aXRoQ3JlZGVudGlhbHMgPyAnaW5jbHVkZScgOiAnc2FtZS1vcmlnaW4nLFxuXHRcdFx0c2lnbmFsOiBzaWduYWxcblx0XHR9KS50aGVuKGZ1bmN0aW9uIChyZXNwb25zZSkge1xuXHRcdFx0c2VsZi5fZmV0Y2hSZXNwb25zZSA9IHJlc3BvbnNlXG5cdFx0XHRzZWxmLl9jb25uZWN0KClcblx0XHR9LCBmdW5jdGlvbiAocmVhc29uKSB7XG5cdFx0XHRzZWxmLmVtaXQoJ2Vycm9yJywgcmVhc29uKVxuXHRcdH0pXG5cdH0gZWxzZSB7XG5cdFx0dmFyIHhociA9IHNlbGYuX3hociA9IG5ldyBnbG9iYWwuWE1MSHR0cFJlcXVlc3QoKVxuXHRcdHRyeSB7XG5cdFx0XHR4aHIub3BlbihzZWxmLl9vcHRzLm1ldGhvZCwgc2VsZi5fb3B0cy51cmwsIHRydWUpXG5cdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHRwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0c2VsZi5lbWl0KCdlcnJvcicsIGVycilcblx0XHRcdH0pXG5cdFx0XHRyZXR1cm5cblx0XHR9XG5cblx0XHQvLyBDYW4ndCBzZXQgcmVzcG9uc2VUeXBlIG9uIHJlYWxseSBvbGQgYnJvd3NlcnNcblx0XHRpZiAoJ3Jlc3BvbnNlVHlwZScgaW4geGhyKVxuXHRcdFx0eGhyLnJlc3BvbnNlVHlwZSA9IHNlbGYuX21vZGUuc3BsaXQoJzonKVswXVxuXG5cdFx0aWYgKCd3aXRoQ3JlZGVudGlhbHMnIGluIHhocilcblx0XHRcdHhoci53aXRoQ3JlZGVudGlhbHMgPSAhIW9wdHMud2l0aENyZWRlbnRpYWxzXG5cblx0XHRpZiAoc2VsZi5fbW9kZSA9PT0gJ3RleHQnICYmICdvdmVycmlkZU1pbWVUeXBlJyBpbiB4aHIpXG5cdFx0XHR4aHIub3ZlcnJpZGVNaW1lVHlwZSgndGV4dC9wbGFpbjsgY2hhcnNldD14LXVzZXItZGVmaW5lZCcpXG5cblx0XHRpZiAoJ3JlcXVlc3RUaW1lb3V0JyBpbiBvcHRzKSB7XG5cdFx0XHR4aHIudGltZW91dCA9IG9wdHMucmVxdWVzdFRpbWVvdXRcblx0XHRcdHhoci5vbnRpbWVvdXQgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHNlbGYuZW1pdCgncmVxdWVzdFRpbWVvdXQnKVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGhlYWRlcnNMaXN0LmZvckVhY2goZnVuY3Rpb24gKGhlYWRlcikge1xuXHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoaGVhZGVyWzBdLCBoZWFkZXJbMV0pXG5cdFx0fSlcblxuXHRcdHNlbGYuX3Jlc3BvbnNlID0gbnVsbFxuXHRcdHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRzd2l0Y2ggKHhoci5yZWFkeVN0YXRlKSB7XG5cdFx0XHRcdGNhc2UgclN0YXRlcy5MT0FESU5HOlxuXHRcdFx0XHRjYXNlIHJTdGF0ZXMuRE9ORTpcblx0XHRcdFx0XHRzZWxmLl9vblhIUlByb2dyZXNzKClcblx0XHRcdFx0XHRicmVha1xuXHRcdFx0fVxuXHRcdH1cblx0XHQvLyBOZWNlc3NhcnkgZm9yIHN0cmVhbWluZyBpbiBGaXJlZm94LCBzaW5jZSB4aHIucmVzcG9uc2UgaXMgT05MWSBkZWZpbmVkXG5cdFx0Ly8gaW4gb25wcm9ncmVzcywgbm90IGluIG9ucmVhZHlzdGF0ZWNoYW5nZSB3aXRoIHhoci5yZWFkeVN0YXRlID0gM1xuXHRcdGlmIChzZWxmLl9tb2RlID09PSAnbW96LWNodW5rZWQtYXJyYXlidWZmZXInKSB7XG5cdFx0XHR4aHIub25wcm9ncmVzcyA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0c2VsZi5fb25YSFJQcm9ncmVzcygpXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0eGhyLm9uZXJyb3IgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAoc2VsZi5fZGVzdHJveWVkKVxuXHRcdFx0XHRyZXR1cm5cblx0XHRcdHNlbGYuZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IoJ1hIUiBlcnJvcicpKVxuXHRcdH1cblxuXHRcdHRyeSB7XG5cdFx0XHR4aHIuc2VuZChib2R5KVxuXHRcdH0gY2F0Y2ggKGVycikge1xuXHRcdFx0cHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHNlbGYuZW1pdCgnZXJyb3InLCBlcnIpXG5cdFx0XHR9KVxuXHRcdFx0cmV0dXJuXG5cdFx0fVxuXHR9XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHhoci5zdGF0dXMgaXMgcmVhZGFibGUgYW5kIG5vbi16ZXJvLCBpbmRpY2F0aW5nIG5vIGVycm9yLlxuICogRXZlbiB0aG91Z2ggdGhlIHNwZWMgc2F5cyBpdCBzaG91bGQgYmUgYXZhaWxhYmxlIGluIHJlYWR5U3RhdGUgMyxcbiAqIGFjY2Vzc2luZyBpdCB0aHJvd3MgYW4gZXhjZXB0aW9uIGluIElFOFxuICovXG5mdW5jdGlvbiBzdGF0dXNWYWxpZCAoeGhyKSB7XG5cdHRyeSB7XG5cdFx0dmFyIHN0YXR1cyA9IHhoci5zdGF0dXNcblx0XHRyZXR1cm4gKHN0YXR1cyAhPT0gbnVsbCAmJiBzdGF0dXMgIT09IDApXG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRyZXR1cm4gZmFsc2Vcblx0fVxufVxuXG5DbGllbnRSZXF1ZXN0LnByb3RvdHlwZS5fb25YSFJQcm9ncmVzcyA9IGZ1bmN0aW9uICgpIHtcblx0dmFyIHNlbGYgPSB0aGlzXG5cblx0aWYgKCFzdGF0dXNWYWxpZChzZWxmLl94aHIpIHx8IHNlbGYuX2Rlc3Ryb3llZClcblx0XHRyZXR1cm5cblxuXHRpZiAoIXNlbGYuX3Jlc3BvbnNlKVxuXHRcdHNlbGYuX2Nvbm5lY3QoKVxuXG5cdHNlbGYuX3Jlc3BvbnNlLl9vblhIUlByb2dyZXNzKClcbn1cblxuQ2xpZW50UmVxdWVzdC5wcm90b3R5cGUuX2Nvbm5lY3QgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXG5cdGlmIChzZWxmLl9kZXN0cm95ZWQpXG5cdFx0cmV0dXJuXG5cblx0c2VsZi5fcmVzcG9uc2UgPSBuZXcgSW5jb21pbmdNZXNzYWdlKHNlbGYuX3hociwgc2VsZi5fZmV0Y2hSZXNwb25zZSwgc2VsZi5fbW9kZSlcblx0c2VsZi5fcmVzcG9uc2Uub24oJ2Vycm9yJywgZnVuY3Rpb24oZXJyKSB7XG5cdFx0c2VsZi5lbWl0KCdlcnJvcicsIGVycilcblx0fSlcblxuXHRzZWxmLmVtaXQoJ3Jlc3BvbnNlJywgc2VsZi5fcmVzcG9uc2UpXG59XG5cbkNsaWVudFJlcXVlc3QucHJvdG90eXBlLl93cml0ZSA9IGZ1bmN0aW9uIChjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXG5cdHNlbGYuX2JvZHkucHVzaChjaHVuaylcblx0Y2IoKVxufVxuXG5DbGllbnRSZXF1ZXN0LnByb3RvdHlwZS5hYm9ydCA9IENsaWVudFJlcXVlc3QucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXHRzZWxmLl9kZXN0cm95ZWQgPSB0cnVlXG5cdGlmIChzZWxmLl9yZXNwb25zZSlcblx0XHRzZWxmLl9yZXNwb25zZS5fZGVzdHJveWVkID0gdHJ1ZVxuXHRpZiAoc2VsZi5feGhyKVxuXHRcdHNlbGYuX3hoci5hYm9ydCgpXG5cdGVsc2UgaWYgKHNlbGYuX2ZldGNoQWJvcnRDb250cm9sbGVyKVxuXHRcdHNlbGYuX2ZldGNoQWJvcnRDb250cm9sbGVyLmFib3J0KClcbn1cblxuQ2xpZW50UmVxdWVzdC5wcm90b3R5cGUuZW5kID0gZnVuY3Rpb24gKGRhdGEsIGVuY29kaW5nLCBjYikge1xuXHR2YXIgc2VsZiA9IHRoaXNcblx0aWYgKHR5cGVvZiBkYXRhID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0Y2IgPSBkYXRhXG5cdFx0ZGF0YSA9IHVuZGVmaW5lZFxuXHR9XG5cblx0c3RyZWFtLldyaXRhYmxlLnByb3RvdHlwZS5lbmQuY2FsbChzZWxmLCBkYXRhLCBlbmNvZGluZywgY2IpXG59XG5cbkNsaWVudFJlcXVlc3QucHJvdG90eXBlLmZsdXNoSGVhZGVycyA9IGZ1bmN0aW9uICgpIHt9XG5DbGllbnRSZXF1ZXN0LnByb3RvdHlwZS5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKCkge31cbkNsaWVudFJlcXVlc3QucHJvdG90eXBlLnNldE5vRGVsYXkgPSBmdW5jdGlvbiAoKSB7fVxuQ2xpZW50UmVxdWVzdC5wcm90b3R5cGUuc2V0U29ja2V0S2VlcEFsaXZlID0gZnVuY3Rpb24gKCkge31cblxuLy8gVGFrZW4gZnJvbSBodHRwOi8vd3d3LnczLm9yZy9UUi9YTUxIdHRwUmVxdWVzdC8jdGhlLXNldHJlcXVlc3RoZWFkZXIlMjglMjktbWV0aG9kXG52YXIgdW5zYWZlSGVhZGVycyA9IFtcblx0J2FjY2VwdC1jaGFyc2V0Jyxcblx0J2FjY2VwdC1lbmNvZGluZycsXG5cdCdhY2Nlc3MtY29udHJvbC1yZXF1ZXN0LWhlYWRlcnMnLFxuXHQnYWNjZXNzLWNvbnRyb2wtcmVxdWVzdC1tZXRob2QnLFxuXHQnY29ubmVjdGlvbicsXG5cdCdjb250ZW50LWxlbmd0aCcsXG5cdCdjb29raWUnLFxuXHQnY29va2llMicsXG5cdCdkYXRlJyxcblx0J2RudCcsXG5cdCdleHBlY3QnLFxuXHQnaG9zdCcsXG5cdCdrZWVwLWFsaXZlJyxcblx0J29yaWdpbicsXG5cdCdyZWZlcmVyJyxcblx0J3RlJyxcblx0J3RyYWlsZXInLFxuXHQndHJhbnNmZXItZW5jb2RpbmcnLFxuXHQndXBncmFkZScsXG5cdCd1c2VyLWFnZW50Jyxcblx0J3ZpYSdcbl1cbiIsInZhciBjYXBhYmlsaXR5ID0gcmVxdWlyZSgnLi9jYXBhYmlsaXR5JylcbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJylcbnZhciBzdHJlYW0gPSByZXF1aXJlKCdyZWFkYWJsZS1zdHJlYW0nKVxuXG52YXIgclN0YXRlcyA9IGV4cG9ydHMucmVhZHlTdGF0ZXMgPSB7XG5cdFVOU0VOVDogMCxcblx0T1BFTkVEOiAxLFxuXHRIRUFERVJTX1JFQ0VJVkVEOiAyLFxuXHRMT0FESU5HOiAzLFxuXHRET05FOiA0XG59XG5cbnZhciBJbmNvbWluZ01lc3NhZ2UgPSBleHBvcnRzLkluY29taW5nTWVzc2FnZSA9IGZ1bmN0aW9uICh4aHIsIHJlc3BvbnNlLCBtb2RlKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXHRzdHJlYW0uUmVhZGFibGUuY2FsbChzZWxmKVxuXG5cdHNlbGYuX21vZGUgPSBtb2RlXG5cdHNlbGYuaGVhZGVycyA9IHt9XG5cdHNlbGYucmF3SGVhZGVycyA9IFtdXG5cdHNlbGYudHJhaWxlcnMgPSB7fVxuXHRzZWxmLnJhd1RyYWlsZXJzID0gW11cblxuXHQvLyBGYWtlIHRoZSAnY2xvc2UnIGV2ZW50LCBidXQgb25seSBvbmNlICdlbmQnIGZpcmVzXG5cdHNlbGYub24oJ2VuZCcsIGZ1bmN0aW9uICgpIHtcblx0XHQvLyBUaGUgbmV4dFRpY2sgaXMgbmVjZXNzYXJ5IHRvIHByZXZlbnQgdGhlICdyZXF1ZXN0JyBtb2R1bGUgZnJvbSBjYXVzaW5nIGFuIGluZmluaXRlIGxvb3Bcblx0XHRwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uICgpIHtcblx0XHRcdHNlbGYuZW1pdCgnY2xvc2UnKVxuXHRcdH0pXG5cdH0pXG5cblx0aWYgKG1vZGUgPT09ICdmZXRjaCcpIHtcblx0XHRzZWxmLl9mZXRjaFJlc3BvbnNlID0gcmVzcG9uc2VcblxuXHRcdHNlbGYudXJsID0gcmVzcG9uc2UudXJsXG5cdFx0c2VsZi5zdGF0dXNDb2RlID0gcmVzcG9uc2Uuc3RhdHVzXG5cdFx0c2VsZi5zdGF0dXNNZXNzYWdlID0gcmVzcG9uc2Uuc3RhdHVzVGV4dFxuXHRcdFxuXHRcdHJlc3BvbnNlLmhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbiAoaGVhZGVyLCBrZXkpe1xuXHRcdFx0c2VsZi5oZWFkZXJzW2tleS50b0xvd2VyQ2FzZSgpXSA9IGhlYWRlclxuXHRcdFx0c2VsZi5yYXdIZWFkZXJzLnB1c2goa2V5LCBoZWFkZXIpXG5cdFx0fSlcblxuXHRcdGlmIChjYXBhYmlsaXR5LndyaXRhYmxlU3RyZWFtKSB7XG5cdFx0XHR2YXIgd3JpdGFibGUgPSBuZXcgV3JpdGFibGVTdHJlYW0oe1xuXHRcdFx0XHR3cml0ZTogZnVuY3Rpb24gKGNodW5rKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblx0XHRcdFx0XHRcdGlmIChzZWxmLl9kZXN0cm95ZWQpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuXG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYoc2VsZi5wdXNoKG5ldyBCdWZmZXIoY2h1bmspKSkge1xuXHRcdFx0XHRcdFx0XHRyZXNvbHZlKClcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHNlbGYuX3Jlc3VtZUZldGNoID0gcmVzb2x2ZVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGNsb3NlOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0aWYgKCFzZWxmLl9kZXN0cm95ZWQpXG5cdFx0XHRcdFx0XHRzZWxmLnB1c2gobnVsbClcblx0XHRcdFx0fSxcblx0XHRcdFx0YWJvcnQ6IGZ1bmN0aW9uIChlcnIpIHtcblx0XHRcdFx0XHRpZiAoIXNlbGYuX2Rlc3Ryb3llZClcblx0XHRcdFx0XHRcdHNlbGYuZW1pdCgnZXJyb3InLCBlcnIpXG5cdFx0XHRcdH1cblx0XHRcdH0pXG5cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHJlc3BvbnNlLmJvZHkucGlwZVRvKHdyaXRhYmxlKVxuXHRcdFx0XHRyZXR1cm5cblx0XHRcdH0gY2F0Y2ggKGUpIHt9IC8vIHBpcGVUbyBtZXRob2QgaXNuJ3QgZGVmaW5lZC4gQ2FuJ3QgZmluZCBhIGJldHRlciB3YXkgdG8gZmVhdHVyZSB0ZXN0IHRoaXNcblx0XHR9XG5cdFx0Ly8gZmFsbGJhY2sgZm9yIHdoZW4gd3JpdGFibGVTdHJlYW0gb3IgcGlwZVRvIGFyZW4ndCBhdmFpbGFibGVcblx0XHR2YXIgcmVhZGVyID0gcmVzcG9uc2UuYm9keS5nZXRSZWFkZXIoKVxuXHRcdGZ1bmN0aW9uIHJlYWQgKCkge1xuXHRcdFx0cmVhZGVyLnJlYWQoKS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHtcblx0XHRcdFx0aWYgKHNlbGYuX2Rlc3Ryb3llZClcblx0XHRcdFx0XHRyZXR1cm5cblx0XHRcdFx0aWYgKHJlc3VsdC5kb25lKSB7XG5cdFx0XHRcdFx0c2VsZi5wdXNoKG51bGwpXG5cdFx0XHRcdFx0cmV0dXJuXG5cdFx0XHRcdH1cblx0XHRcdFx0c2VsZi5wdXNoKG5ldyBCdWZmZXIocmVzdWx0LnZhbHVlKSlcblx0XHRcdFx0cmVhZCgpXG5cdFx0XHR9KS5jYXRjaChmdW5jdGlvbihlcnIpIHtcblx0XHRcdFx0aWYgKCFzZWxmLl9kZXN0cm95ZWQpXG5cdFx0XHRcdFx0c2VsZi5lbWl0KCdlcnJvcicsIGVycilcblx0XHRcdH0pXG5cdFx0fVxuXHRcdHJlYWQoKVxuXHR9IGVsc2Uge1xuXHRcdHNlbGYuX3hociA9IHhoclxuXHRcdHNlbGYuX3BvcyA9IDBcblxuXHRcdHNlbGYudXJsID0geGhyLnJlc3BvbnNlVVJMXG5cdFx0c2VsZi5zdGF0dXNDb2RlID0geGhyLnN0YXR1c1xuXHRcdHNlbGYuc3RhdHVzTWVzc2FnZSA9IHhoci5zdGF0dXNUZXh0XG5cdFx0dmFyIGhlYWRlcnMgPSB4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkuc3BsaXQoL1xccj9cXG4vKVxuXHRcdGhlYWRlcnMuZm9yRWFjaChmdW5jdGlvbiAoaGVhZGVyKSB7XG5cdFx0XHR2YXIgbWF0Y2hlcyA9IGhlYWRlci5tYXRjaCgvXihbXjpdKyk6XFxzKiguKikvKVxuXHRcdFx0aWYgKG1hdGNoZXMpIHtcblx0XHRcdFx0dmFyIGtleSA9IG1hdGNoZXNbMV0udG9Mb3dlckNhc2UoKVxuXHRcdFx0XHRpZiAoa2V5ID09PSAnc2V0LWNvb2tpZScpIHtcblx0XHRcdFx0XHRpZiAoc2VsZi5oZWFkZXJzW2tleV0gPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdFx0c2VsZi5oZWFkZXJzW2tleV0gPSBbXVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRzZWxmLmhlYWRlcnNba2V5XS5wdXNoKG1hdGNoZXNbMl0pXG5cdFx0XHRcdH0gZWxzZSBpZiAoc2VsZi5oZWFkZXJzW2tleV0gIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0XHRcdHNlbGYuaGVhZGVyc1trZXldICs9ICcsICcgKyBtYXRjaGVzWzJdXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0c2VsZi5oZWFkZXJzW2tleV0gPSBtYXRjaGVzWzJdXG5cdFx0XHRcdH1cblx0XHRcdFx0c2VsZi5yYXdIZWFkZXJzLnB1c2gobWF0Y2hlc1sxXSwgbWF0Y2hlc1syXSlcblx0XHRcdH1cblx0XHR9KVxuXG5cdFx0c2VsZi5fY2hhcnNldCA9ICd4LXVzZXItZGVmaW5lZCdcblx0XHRpZiAoIWNhcGFiaWxpdHkub3ZlcnJpZGVNaW1lVHlwZSkge1xuXHRcdFx0dmFyIG1pbWVUeXBlID0gc2VsZi5yYXdIZWFkZXJzWydtaW1lLXR5cGUnXVxuXHRcdFx0aWYgKG1pbWVUeXBlKSB7XG5cdFx0XHRcdHZhciBjaGFyc2V0TWF0Y2ggPSBtaW1lVHlwZS5tYXRjaCgvO1xccypjaGFyc2V0PShbXjtdKSg7fCQpLylcblx0XHRcdFx0aWYgKGNoYXJzZXRNYXRjaCkge1xuXHRcdFx0XHRcdHNlbGYuX2NoYXJzZXQgPSBjaGFyc2V0TWF0Y2hbMV0udG9Mb3dlckNhc2UoKVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoIXNlbGYuX2NoYXJzZXQpXG5cdFx0XHRcdHNlbGYuX2NoYXJzZXQgPSAndXRmLTgnIC8vIGJlc3QgZ3Vlc3Ncblx0XHR9XG5cdH1cbn1cblxuaW5oZXJpdHMoSW5jb21pbmdNZXNzYWdlLCBzdHJlYW0uUmVhZGFibGUpXG5cbkluY29taW5nTWVzc2FnZS5wcm90b3R5cGUuX3JlYWQgPSBmdW5jdGlvbiAoKSB7XG5cdHZhciBzZWxmID0gdGhpc1xuXG5cdHZhciByZXNvbHZlID0gc2VsZi5fcmVzdW1lRmV0Y2hcblx0aWYgKHJlc29sdmUpIHtcblx0XHRzZWxmLl9yZXN1bWVGZXRjaCA9IG51bGxcblx0XHRyZXNvbHZlKClcblx0fVxufVxuXG5JbmNvbWluZ01lc3NhZ2UucHJvdG90eXBlLl9vblhIUlByb2dyZXNzID0gZnVuY3Rpb24gKCkge1xuXHR2YXIgc2VsZiA9IHRoaXNcblxuXHR2YXIgeGhyID0gc2VsZi5feGhyXG5cblx0dmFyIHJlc3BvbnNlID0gbnVsbFxuXHRzd2l0Y2ggKHNlbGYuX21vZGUpIHtcblx0XHRjYXNlICd0ZXh0OnZiYXJyYXknOiAvLyBGb3IgSUU5XG5cdFx0XHRpZiAoeGhyLnJlYWR5U3RhdGUgIT09IHJTdGF0ZXMuRE9ORSlcblx0XHRcdFx0YnJlYWtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdC8vIFRoaXMgZmFpbHMgaW4gSUU4XG5cdFx0XHRcdHJlc3BvbnNlID0gbmV3IGdsb2JhbC5WQkFycmF5KHhoci5yZXNwb25zZUJvZHkpLnRvQXJyYXkoKVxuXHRcdFx0fSBjYXRjaCAoZSkge31cblx0XHRcdGlmIChyZXNwb25zZSAhPT0gbnVsbCkge1xuXHRcdFx0XHRzZWxmLnB1c2gobmV3IEJ1ZmZlcihyZXNwb25zZSkpXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHR9XG5cdFx0XHQvLyBGYWxscyB0aHJvdWdoIGluIElFOFx0XG5cdFx0Y2FzZSAndGV4dCc6XG5cdFx0XHR0cnkgeyAvLyBUaGlzIHdpbGwgZmFpbCB3aGVuIHJlYWR5U3RhdGUgPSAzIGluIElFOS4gU3dpdGNoIG1vZGUgYW5kIHdhaXQgZm9yIHJlYWR5U3RhdGUgPSA0XG5cdFx0XHRcdHJlc3BvbnNlID0geGhyLnJlc3BvbnNlVGV4dFxuXHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRzZWxmLl9tb2RlID0gJ3RleHQ6dmJhcnJheSdcblx0XHRcdFx0YnJlYWtcblx0XHRcdH1cblx0XHRcdGlmIChyZXNwb25zZS5sZW5ndGggPiBzZWxmLl9wb3MpIHtcblx0XHRcdFx0dmFyIG5ld0RhdGEgPSByZXNwb25zZS5zdWJzdHIoc2VsZi5fcG9zKVxuXHRcdFx0XHRpZiAoc2VsZi5fY2hhcnNldCA9PT0gJ3gtdXNlci1kZWZpbmVkJykge1xuXHRcdFx0XHRcdHZhciBidWZmZXIgPSBuZXcgQnVmZmVyKG5ld0RhdGEubGVuZ3RoKVxuXHRcdFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbmV3RGF0YS5sZW5ndGg7IGkrKylcblx0XHRcdFx0XHRcdGJ1ZmZlcltpXSA9IG5ld0RhdGEuY2hhckNvZGVBdChpKSAmIDB4ZmZcblxuXHRcdFx0XHRcdHNlbGYucHVzaChidWZmZXIpXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0c2VsZi5wdXNoKG5ld0RhdGEsIHNlbGYuX2NoYXJzZXQpXG5cdFx0XHRcdH1cblx0XHRcdFx0c2VsZi5fcG9zID0gcmVzcG9uc2UubGVuZ3RoXG5cdFx0XHR9XG5cdFx0XHRicmVha1xuXHRcdGNhc2UgJ2FycmF5YnVmZmVyJzpcblx0XHRcdGlmICh4aHIucmVhZHlTdGF0ZSAhPT0gclN0YXRlcy5ET05FIHx8ICF4aHIucmVzcG9uc2UpXG5cdFx0XHRcdGJyZWFrXG5cdFx0XHRyZXNwb25zZSA9IHhoci5yZXNwb25zZVxuXHRcdFx0c2VsZi5wdXNoKG5ldyBCdWZmZXIobmV3IFVpbnQ4QXJyYXkocmVzcG9uc2UpKSlcblx0XHRcdGJyZWFrXG5cdFx0Y2FzZSAnbW96LWNodW5rZWQtYXJyYXlidWZmZXInOiAvLyB0YWtlIHdob2xlXG5cdFx0XHRyZXNwb25zZSA9IHhoci5yZXNwb25zZVxuXHRcdFx0aWYgKHhoci5yZWFkeVN0YXRlICE9PSByU3RhdGVzLkxPQURJTkcgfHwgIXJlc3BvbnNlKVxuXHRcdFx0XHRicmVha1xuXHRcdFx0c2VsZi5wdXNoKG5ldyBCdWZmZXIobmV3IFVpbnQ4QXJyYXkocmVzcG9uc2UpKSlcblx0XHRcdGJyZWFrXG5cdFx0Y2FzZSAnbXMtc3RyZWFtJzpcblx0XHRcdHJlc3BvbnNlID0geGhyLnJlc3BvbnNlXG5cdFx0XHRpZiAoeGhyLnJlYWR5U3RhdGUgIT09IHJTdGF0ZXMuTE9BRElORylcblx0XHRcdFx0YnJlYWtcblx0XHRcdHZhciByZWFkZXIgPSBuZXcgZ2xvYmFsLk1TU3RyZWFtUmVhZGVyKClcblx0XHRcdHJlYWRlci5vbnByb2dyZXNzID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRpZiAocmVhZGVyLnJlc3VsdC5ieXRlTGVuZ3RoID4gc2VsZi5fcG9zKSB7XG5cdFx0XHRcdFx0c2VsZi5wdXNoKG5ldyBCdWZmZXIobmV3IFVpbnQ4QXJyYXkocmVhZGVyLnJlc3VsdC5zbGljZShzZWxmLl9wb3MpKSkpXG5cdFx0XHRcdFx0c2VsZi5fcG9zID0gcmVhZGVyLnJlc3VsdC5ieXRlTGVuZ3RoXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJlYWRlci5vbmxvYWQgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHNlbGYucHVzaChudWxsKVxuXHRcdFx0fVxuXHRcdFx0Ly8gcmVhZGVyLm9uZXJyb3IgPSA/Pz8gLy8gVE9ETzogdGhpc1xuXHRcdFx0cmVhZGVyLnJlYWRBc0FycmF5QnVmZmVyKHJlc3BvbnNlKVxuXHRcdFx0YnJlYWtcblx0fVxuXG5cdC8vIFRoZSBtcy1zdHJlYW0gY2FzZSBoYW5kbGVzIGVuZCBzZXBhcmF0ZWx5IGluIHJlYWRlci5vbmxvYWQoKVxuXHRpZiAoc2VsZi5feGhyLnJlYWR5U3RhdGUgPT09IHJTdGF0ZXMuRE9ORSAmJiBzZWxmLl9tb2RlICE9PSAnbXMtc3RyZWFtJykge1xuXHRcdHNlbGYucHVzaChudWxsKVxuXHR9XG59XG4iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuJ3VzZSBzdHJpY3QnO1xuXG4vKjxyZXBsYWNlbWVudD4qL1xuXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnc2FmZS1idWZmZXInKS5CdWZmZXI7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxudmFyIGlzRW5jb2RpbmcgPSBCdWZmZXIuaXNFbmNvZGluZyB8fCBmdW5jdGlvbiAoZW5jb2RpbmcpIHtcbiAgZW5jb2RpbmcgPSAnJyArIGVuY29kaW5nO1xuICBzd2l0Y2ggKGVuY29kaW5nICYmIGVuY29kaW5nLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOmNhc2UgJ3V0ZjgnOmNhc2UgJ3V0Zi04JzpjYXNlICdhc2NpaSc6Y2FzZSAnYmluYXJ5JzpjYXNlICdiYXNlNjQnOmNhc2UgJ3VjczInOmNhc2UgJ3Vjcy0yJzpjYXNlICd1dGYxNmxlJzpjYXNlICd1dGYtMTZsZSc6Y2FzZSAncmF3JzpcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIF9ub3JtYWxpemVFbmNvZGluZyhlbmMpIHtcbiAgaWYgKCFlbmMpIHJldHVybiAndXRmOCc7XG4gIHZhciByZXRyaWVkO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIHN3aXRjaCAoZW5jKSB7XG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuICd1dGY4JztcbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiAndXRmMTZsZSc7XG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuICdsYXRpbjEnO1xuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBlbmM7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAocmV0cmllZCkgcmV0dXJuOyAvLyB1bmRlZmluZWRcbiAgICAgICAgZW5jID0gKCcnICsgZW5jKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICByZXRyaWVkID0gdHJ1ZTtcbiAgICB9XG4gIH1cbn07XG5cbi8vIERvIG5vdCBjYWNoZSBgQnVmZmVyLmlzRW5jb2RpbmdgIHdoZW4gY2hlY2tpbmcgZW5jb2RpbmcgbmFtZXMgYXMgc29tZVxuLy8gbW9kdWxlcyBtb25rZXktcGF0Y2ggaXQgdG8gc3VwcG9ydCBhZGRpdGlvbmFsIGVuY29kaW5nc1xuZnVuY3Rpb24gbm9ybWFsaXplRW5jb2RpbmcoZW5jKSB7XG4gIHZhciBuZW5jID0gX25vcm1hbGl6ZUVuY29kaW5nKGVuYyk7XG4gIGlmICh0eXBlb2YgbmVuYyAhPT0gJ3N0cmluZycgJiYgKEJ1ZmZlci5pc0VuY29kaW5nID09PSBpc0VuY29kaW5nIHx8ICFpc0VuY29kaW5nKGVuYykpKSB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmMpO1xuICByZXR1cm4gbmVuYyB8fCBlbmM7XG59XG5cbi8vIFN0cmluZ0RlY29kZXIgcHJvdmlkZXMgYW4gaW50ZXJmYWNlIGZvciBlZmZpY2llbnRseSBzcGxpdHRpbmcgYSBzZXJpZXMgb2Zcbi8vIGJ1ZmZlcnMgaW50byBhIHNlcmllcyBvZiBKUyBzdHJpbmdzIHdpdGhvdXQgYnJlYWtpbmcgYXBhcnQgbXVsdGktYnl0ZVxuLy8gY2hhcmFjdGVycy5cbmV4cG9ydHMuU3RyaW5nRGVjb2RlciA9IFN0cmluZ0RlY29kZXI7XG5mdW5jdGlvbiBTdHJpbmdEZWNvZGVyKGVuY29kaW5nKSB7XG4gIHRoaXMuZW5jb2RpbmcgPSBub3JtYWxpemVFbmNvZGluZyhlbmNvZGluZyk7XG4gIHZhciBuYjtcbiAgc3dpdGNoICh0aGlzLmVuY29kaW5nKSB7XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICB0aGlzLnRleHQgPSB1dGYxNlRleHQ7XG4gICAgICB0aGlzLmVuZCA9IHV0ZjE2RW5kO1xuICAgICAgbmIgPSA0O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndXRmOCc6XG4gICAgICB0aGlzLmZpbGxMYXN0ID0gdXRmOEZpbGxMYXN0O1xuICAgICAgbmIgPSA0O1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgIHRoaXMudGV4dCA9IGJhc2U2NFRleHQ7XG4gICAgICB0aGlzLmVuZCA9IGJhc2U2NEVuZDtcbiAgICAgIG5iID0gMztcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aGlzLndyaXRlID0gc2ltcGxlV3JpdGU7XG4gICAgICB0aGlzLmVuZCA9IHNpbXBsZUVuZDtcbiAgICAgIHJldHVybjtcbiAgfVxuICB0aGlzLmxhc3ROZWVkID0gMDtcbiAgdGhpcy5sYXN0VG90YWwgPSAwO1xuICB0aGlzLmxhc3RDaGFyID0gQnVmZmVyLmFsbG9jVW5zYWZlKG5iKTtcbn1cblxuU3RyaW5nRGVjb2Rlci5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiAoYnVmKSB7XG4gIGlmIChidWYubGVuZ3RoID09PSAwKSByZXR1cm4gJyc7XG4gIHZhciByO1xuICB2YXIgaTtcbiAgaWYgKHRoaXMubGFzdE5lZWQpIHtcbiAgICByID0gdGhpcy5maWxsTGFzdChidWYpO1xuICAgIGlmIChyID09PSB1bmRlZmluZWQpIHJldHVybiAnJztcbiAgICBpID0gdGhpcy5sYXN0TmVlZDtcbiAgICB0aGlzLmxhc3ROZWVkID0gMDtcbiAgfSBlbHNlIHtcbiAgICBpID0gMDtcbiAgfVxuICBpZiAoaSA8IGJ1Zi5sZW5ndGgpIHJldHVybiByID8gciArIHRoaXMudGV4dChidWYsIGkpIDogdGhpcy50ZXh0KGJ1ZiwgaSk7XG4gIHJldHVybiByIHx8ICcnO1xufTtcblxuU3RyaW5nRGVjb2Rlci5wcm90b3R5cGUuZW5kID0gdXRmOEVuZDtcblxuLy8gUmV0dXJucyBvbmx5IGNvbXBsZXRlIGNoYXJhY3RlcnMgaW4gYSBCdWZmZXJcblN0cmluZ0RlY29kZXIucHJvdG90eXBlLnRleHQgPSB1dGY4VGV4dDtcblxuLy8gQXR0ZW1wdHMgdG8gY29tcGxldGUgYSBwYXJ0aWFsIG5vbi1VVEYtOCBjaGFyYWN0ZXIgdXNpbmcgYnl0ZXMgZnJvbSBhIEJ1ZmZlclxuU3RyaW5nRGVjb2Rlci5wcm90b3R5cGUuZmlsbExhc3QgPSBmdW5jdGlvbiAoYnVmKSB7XG4gIGlmICh0aGlzLmxhc3ROZWVkIDw9IGJ1Zi5sZW5ndGgpIHtcbiAgICBidWYuY29weSh0aGlzLmxhc3RDaGFyLCB0aGlzLmxhc3RUb3RhbCAtIHRoaXMubGFzdE5lZWQsIDAsIHRoaXMubGFzdE5lZWQpO1xuICAgIHJldHVybiB0aGlzLmxhc3RDaGFyLnRvU3RyaW5nKHRoaXMuZW5jb2RpbmcsIDAsIHRoaXMubGFzdFRvdGFsKTtcbiAgfVxuICBidWYuY29weSh0aGlzLmxhc3RDaGFyLCB0aGlzLmxhc3RUb3RhbCAtIHRoaXMubGFzdE5lZWQsIDAsIGJ1Zi5sZW5ndGgpO1xuICB0aGlzLmxhc3ROZWVkIC09IGJ1Zi5sZW5ndGg7XG59O1xuXG4vLyBDaGVja3MgdGhlIHR5cGUgb2YgYSBVVEYtOCBieXRlLCB3aGV0aGVyIGl0J3MgQVNDSUksIGEgbGVhZGluZyBieXRlLCBvciBhXG4vLyBjb250aW51YXRpb24gYnl0ZS4gSWYgYW4gaW52YWxpZCBieXRlIGlzIGRldGVjdGVkLCAtMiBpcyByZXR1cm5lZC5cbmZ1bmN0aW9uIHV0ZjhDaGVja0J5dGUoYnl0ZSkge1xuICBpZiAoYnl0ZSA8PSAweDdGKSByZXR1cm4gMDtlbHNlIGlmIChieXRlID4+IDUgPT09IDB4MDYpIHJldHVybiAyO2Vsc2UgaWYgKGJ5dGUgPj4gNCA9PT0gMHgwRSkgcmV0dXJuIDM7ZWxzZSBpZiAoYnl0ZSA+PiAzID09PSAweDFFKSByZXR1cm4gNDtcbiAgcmV0dXJuIGJ5dGUgPj4gNiA9PT0gMHgwMiA/IC0xIDogLTI7XG59XG5cbi8vIENoZWNrcyBhdCBtb3N0IDMgYnl0ZXMgYXQgdGhlIGVuZCBvZiBhIEJ1ZmZlciBpbiBvcmRlciB0byBkZXRlY3QgYW5cbi8vIGluY29tcGxldGUgbXVsdGktYnl0ZSBVVEYtOCBjaGFyYWN0ZXIuIFRoZSB0b3RhbCBudW1iZXIgb2YgYnl0ZXMgKDIsIDMsIG9yIDQpXG4vLyBuZWVkZWQgdG8gY29tcGxldGUgdGhlIFVURi04IGNoYXJhY3RlciAoaWYgYXBwbGljYWJsZSkgYXJlIHJldHVybmVkLlxuZnVuY3Rpb24gdXRmOENoZWNrSW5jb21wbGV0ZShzZWxmLCBidWYsIGkpIHtcbiAgdmFyIGogPSBidWYubGVuZ3RoIC0gMTtcbiAgaWYgKGogPCBpKSByZXR1cm4gMDtcbiAgdmFyIG5iID0gdXRmOENoZWNrQnl0ZShidWZbal0pO1xuICBpZiAobmIgPj0gMCkge1xuICAgIGlmIChuYiA+IDApIHNlbGYubGFzdE5lZWQgPSBuYiAtIDE7XG4gICAgcmV0dXJuIG5iO1xuICB9XG4gIGlmICgtLWogPCBpIHx8IG5iID09PSAtMikgcmV0dXJuIDA7XG4gIG5iID0gdXRmOENoZWNrQnl0ZShidWZbal0pO1xuICBpZiAobmIgPj0gMCkge1xuICAgIGlmIChuYiA+IDApIHNlbGYubGFzdE5lZWQgPSBuYiAtIDI7XG4gICAgcmV0dXJuIG5iO1xuICB9XG4gIGlmICgtLWogPCBpIHx8IG5iID09PSAtMikgcmV0dXJuIDA7XG4gIG5iID0gdXRmOENoZWNrQnl0ZShidWZbal0pO1xuICBpZiAobmIgPj0gMCkge1xuICAgIGlmIChuYiA+IDApIHtcbiAgICAgIGlmIChuYiA9PT0gMikgbmIgPSAwO2Vsc2Ugc2VsZi5sYXN0TmVlZCA9IG5iIC0gMztcbiAgICB9XG4gICAgcmV0dXJuIG5iO1xuICB9XG4gIHJldHVybiAwO1xufVxuXG4vLyBWYWxpZGF0ZXMgYXMgbWFueSBjb250aW51YXRpb24gYnl0ZXMgZm9yIGEgbXVsdGktYnl0ZSBVVEYtOCBjaGFyYWN0ZXIgYXNcbi8vIG5lZWRlZCBvciBhcmUgYXZhaWxhYmxlLiBJZiB3ZSBzZWUgYSBub24tY29udGludWF0aW9uIGJ5dGUgd2hlcmUgd2UgZXhwZWN0XG4vLyBvbmUsIHdlIFwicmVwbGFjZVwiIHRoZSB2YWxpZGF0ZWQgY29udGludWF0aW9uIGJ5dGVzIHdlJ3ZlIHNlZW4gc28gZmFyIHdpdGhcbi8vIGEgc2luZ2xlIFVURi04IHJlcGxhY2VtZW50IGNoYXJhY3RlciAoJ1xcdWZmZmQnKSwgdG8gbWF0Y2ggdjgncyBVVEYtOCBkZWNvZGluZ1xuLy8gYmVoYXZpb3IuIFRoZSBjb250aW51YXRpb24gYnl0ZSBjaGVjayBpcyBpbmNsdWRlZCB0aHJlZSB0aW1lcyBpbiB0aGUgY2FzZVxuLy8gd2hlcmUgYWxsIG9mIHRoZSBjb250aW51YXRpb24gYnl0ZXMgZm9yIGEgY2hhcmFjdGVyIGV4aXN0IGluIHRoZSBzYW1lIGJ1ZmZlci5cbi8vIEl0IGlzIGFsc28gZG9uZSB0aGlzIHdheSBhcyBhIHNsaWdodCBwZXJmb3JtYW5jZSBpbmNyZWFzZSBpbnN0ZWFkIG9mIHVzaW5nIGFcbi8vIGxvb3AuXG5mdW5jdGlvbiB1dGY4Q2hlY2tFeHRyYUJ5dGVzKHNlbGYsIGJ1ZiwgcCkge1xuICBpZiAoKGJ1ZlswXSAmIDB4QzApICE9PSAweDgwKSB7XG4gICAgc2VsZi5sYXN0TmVlZCA9IDA7XG4gICAgcmV0dXJuICdcXHVmZmZkJztcbiAgfVxuICBpZiAoc2VsZi5sYXN0TmVlZCA+IDEgJiYgYnVmLmxlbmd0aCA+IDEpIHtcbiAgICBpZiAoKGJ1ZlsxXSAmIDB4QzApICE9PSAweDgwKSB7XG4gICAgICBzZWxmLmxhc3ROZWVkID0gMTtcbiAgICAgIHJldHVybiAnXFx1ZmZmZCc7XG4gICAgfVxuICAgIGlmIChzZWxmLmxhc3ROZWVkID4gMiAmJiBidWYubGVuZ3RoID4gMikge1xuICAgICAgaWYgKChidWZbMl0gJiAweEMwKSAhPT0gMHg4MCkge1xuICAgICAgICBzZWxmLmxhc3ROZWVkID0gMjtcbiAgICAgICAgcmV0dXJuICdcXHVmZmZkJztcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLy8gQXR0ZW1wdHMgdG8gY29tcGxldGUgYSBtdWx0aS1ieXRlIFVURi04IGNoYXJhY3RlciB1c2luZyBieXRlcyBmcm9tIGEgQnVmZmVyLlxuZnVuY3Rpb24gdXRmOEZpbGxMYXN0KGJ1Zikge1xuICB2YXIgcCA9IHRoaXMubGFzdFRvdGFsIC0gdGhpcy5sYXN0TmVlZDtcbiAgdmFyIHIgPSB1dGY4Q2hlY2tFeHRyYUJ5dGVzKHRoaXMsIGJ1ZiwgcCk7XG4gIGlmIChyICE9PSB1bmRlZmluZWQpIHJldHVybiByO1xuICBpZiAodGhpcy5sYXN0TmVlZCA8PSBidWYubGVuZ3RoKSB7XG4gICAgYnVmLmNvcHkodGhpcy5sYXN0Q2hhciwgcCwgMCwgdGhpcy5sYXN0TmVlZCk7XG4gICAgcmV0dXJuIHRoaXMubGFzdENoYXIudG9TdHJpbmcodGhpcy5lbmNvZGluZywgMCwgdGhpcy5sYXN0VG90YWwpO1xuICB9XG4gIGJ1Zi5jb3B5KHRoaXMubGFzdENoYXIsIHAsIDAsIGJ1Zi5sZW5ndGgpO1xuICB0aGlzLmxhc3ROZWVkIC09IGJ1Zi5sZW5ndGg7XG59XG5cbi8vIFJldHVybnMgYWxsIGNvbXBsZXRlIFVURi04IGNoYXJhY3RlcnMgaW4gYSBCdWZmZXIuIElmIHRoZSBCdWZmZXIgZW5kZWQgb24gYVxuLy8gcGFydGlhbCBjaGFyYWN0ZXIsIHRoZSBjaGFyYWN0ZXIncyBieXRlcyBhcmUgYnVmZmVyZWQgdW50aWwgdGhlIHJlcXVpcmVkXG4vLyBudW1iZXIgb2YgYnl0ZXMgYXJlIGF2YWlsYWJsZS5cbmZ1bmN0aW9uIHV0ZjhUZXh0KGJ1ZiwgaSkge1xuICB2YXIgdG90YWwgPSB1dGY4Q2hlY2tJbmNvbXBsZXRlKHRoaXMsIGJ1ZiwgaSk7XG4gIGlmICghdGhpcy5sYXN0TmVlZCkgcmV0dXJuIGJ1Zi50b1N0cmluZygndXRmOCcsIGkpO1xuICB0aGlzLmxhc3RUb3RhbCA9IHRvdGFsO1xuICB2YXIgZW5kID0gYnVmLmxlbmd0aCAtICh0b3RhbCAtIHRoaXMubGFzdE5lZWQpO1xuICBidWYuY29weSh0aGlzLmxhc3RDaGFyLCAwLCBlbmQpO1xuICByZXR1cm4gYnVmLnRvU3RyaW5nKCd1dGY4JywgaSwgZW5kKTtcbn1cblxuLy8gRm9yIFVURi04LCBhIHJlcGxhY2VtZW50IGNoYXJhY3RlciBpcyBhZGRlZCB3aGVuIGVuZGluZyBvbiBhIHBhcnRpYWxcbi8vIGNoYXJhY3Rlci5cbmZ1bmN0aW9uIHV0ZjhFbmQoYnVmKSB7XG4gIHZhciByID0gYnVmICYmIGJ1Zi5sZW5ndGggPyB0aGlzLndyaXRlKGJ1ZikgOiAnJztcbiAgaWYgKHRoaXMubGFzdE5lZWQpIHJldHVybiByICsgJ1xcdWZmZmQnO1xuICByZXR1cm4gcjtcbn1cblxuLy8gVVRGLTE2TEUgdHlwaWNhbGx5IG5lZWRzIHR3byBieXRlcyBwZXIgY2hhcmFjdGVyLCBidXQgZXZlbiBpZiB3ZSBoYXZlIGFuIGV2ZW5cbi8vIG51bWJlciBvZiBieXRlcyBhdmFpbGFibGUsIHdlIG5lZWQgdG8gY2hlY2sgaWYgd2UgZW5kIG9uIGEgbGVhZGluZy9oaWdoXG4vLyBzdXJyb2dhdGUuIEluIHRoYXQgY2FzZSwgd2UgbmVlZCB0byB3YWl0IGZvciB0aGUgbmV4dCB0d28gYnl0ZXMgaW4gb3JkZXIgdG9cbi8vIGRlY29kZSB0aGUgbGFzdCBjaGFyYWN0ZXIgcHJvcGVybHkuXG5mdW5jdGlvbiB1dGYxNlRleHQoYnVmLCBpKSB7XG4gIGlmICgoYnVmLmxlbmd0aCAtIGkpICUgMiA9PT0gMCkge1xuICAgIHZhciByID0gYnVmLnRvU3RyaW5nKCd1dGYxNmxlJywgaSk7XG4gICAgaWYgKHIpIHtcbiAgICAgIHZhciBjID0gci5jaGFyQ29kZUF0KHIubGVuZ3RoIC0gMSk7XG4gICAgICBpZiAoYyA+PSAweEQ4MDAgJiYgYyA8PSAweERCRkYpIHtcbiAgICAgICAgdGhpcy5sYXN0TmVlZCA9IDI7XG4gICAgICAgIHRoaXMubGFzdFRvdGFsID0gNDtcbiAgICAgICAgdGhpcy5sYXN0Q2hhclswXSA9IGJ1ZltidWYubGVuZ3RoIC0gMl07XG4gICAgICAgIHRoaXMubGFzdENoYXJbMV0gPSBidWZbYnVmLmxlbmd0aCAtIDFdO1xuICAgICAgICByZXR1cm4gci5zbGljZSgwLCAtMSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByO1xuICB9XG4gIHRoaXMubGFzdE5lZWQgPSAxO1xuICB0aGlzLmxhc3RUb3RhbCA9IDI7XG4gIHRoaXMubGFzdENoYXJbMF0gPSBidWZbYnVmLmxlbmd0aCAtIDFdO1xuICByZXR1cm4gYnVmLnRvU3RyaW5nKCd1dGYxNmxlJywgaSwgYnVmLmxlbmd0aCAtIDEpO1xufVxuXG4vLyBGb3IgVVRGLTE2TEUgd2UgZG8gbm90IGV4cGxpY2l0bHkgYXBwZW5kIHNwZWNpYWwgcmVwbGFjZW1lbnQgY2hhcmFjdGVycyBpZiB3ZVxuLy8gZW5kIG9uIGEgcGFydGlhbCBjaGFyYWN0ZXIsIHdlIHNpbXBseSBsZXQgdjggaGFuZGxlIHRoYXQuXG5mdW5jdGlvbiB1dGYxNkVuZChidWYpIHtcbiAgdmFyIHIgPSBidWYgJiYgYnVmLmxlbmd0aCA/IHRoaXMud3JpdGUoYnVmKSA6ICcnO1xuICBpZiAodGhpcy5sYXN0TmVlZCkge1xuICAgIHZhciBlbmQgPSB0aGlzLmxhc3RUb3RhbCAtIHRoaXMubGFzdE5lZWQ7XG4gICAgcmV0dXJuIHIgKyB0aGlzLmxhc3RDaGFyLnRvU3RyaW5nKCd1dGYxNmxlJywgMCwgZW5kKTtcbiAgfVxuICByZXR1cm4gcjtcbn1cblxuZnVuY3Rpb24gYmFzZTY0VGV4dChidWYsIGkpIHtcbiAgdmFyIG4gPSAoYnVmLmxlbmd0aCAtIGkpICUgMztcbiAgaWYgKG4gPT09IDApIHJldHVybiBidWYudG9TdHJpbmcoJ2Jhc2U2NCcsIGkpO1xuICB0aGlzLmxhc3ROZWVkID0gMyAtIG47XG4gIHRoaXMubGFzdFRvdGFsID0gMztcbiAgaWYgKG4gPT09IDEpIHtcbiAgICB0aGlzLmxhc3RDaGFyWzBdID0gYnVmW2J1Zi5sZW5ndGggLSAxXTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmxhc3RDaGFyWzBdID0gYnVmW2J1Zi5sZW5ndGggLSAyXTtcbiAgICB0aGlzLmxhc3RDaGFyWzFdID0gYnVmW2J1Zi5sZW5ndGggLSAxXTtcbiAgfVxuICByZXR1cm4gYnVmLnRvU3RyaW5nKCdiYXNlNjQnLCBpLCBidWYubGVuZ3RoIC0gbik7XG59XG5cbmZ1bmN0aW9uIGJhc2U2NEVuZChidWYpIHtcbiAgdmFyIHIgPSBidWYgJiYgYnVmLmxlbmd0aCA/IHRoaXMud3JpdGUoYnVmKSA6ICcnO1xuICBpZiAodGhpcy5sYXN0TmVlZCkgcmV0dXJuIHIgKyB0aGlzLmxhc3RDaGFyLnRvU3RyaW5nKCdiYXNlNjQnLCAwLCAzIC0gdGhpcy5sYXN0TmVlZCk7XG4gIHJldHVybiByO1xufVxuXG4vLyBQYXNzIGJ5dGVzIG9uIHRocm91Z2ggZm9yIHNpbmdsZS1ieXRlIGVuY29kaW5ncyAoZS5nLiBhc2NpaSwgbGF0aW4xLCBoZXgpXG5mdW5jdGlvbiBzaW1wbGVXcml0ZShidWYpIHtcbiAgcmV0dXJuIGJ1Zi50b1N0cmluZyh0aGlzLmVuY29kaW5nKTtcbn1cblxuZnVuY3Rpb24gc2ltcGxlRW5kKGJ1Zikge1xuICByZXR1cm4gYnVmICYmIGJ1Zi5sZW5ndGggPyB0aGlzLndyaXRlKGJ1ZikgOiAnJztcbn0iLCJ2YXIgQnVmZmVyID0gcmVxdWlyZSgnYnVmZmVyJykuQnVmZmVyXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJ1Zikge1xuXHQvLyBJZiB0aGUgYnVmZmVyIGlzIGJhY2tlZCBieSBhIFVpbnQ4QXJyYXksIGEgZmFzdGVyIHZlcnNpb24gd2lsbCB3b3JrXG5cdGlmIChidWYgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG5cdFx0Ly8gSWYgdGhlIGJ1ZmZlciBpc24ndCBhIHN1YmFycmF5LCByZXR1cm4gdGhlIHVuZGVybHlpbmcgQXJyYXlCdWZmZXJcblx0XHRpZiAoYnVmLmJ5dGVPZmZzZXQgPT09IDAgJiYgYnVmLmJ5dGVMZW5ndGggPT09IGJ1Zi5idWZmZXIuYnl0ZUxlbmd0aCkge1xuXHRcdFx0cmV0dXJuIGJ1Zi5idWZmZXJcblx0XHR9IGVsc2UgaWYgKHR5cGVvZiBidWYuYnVmZmVyLnNsaWNlID09PSAnZnVuY3Rpb24nKSB7XG5cdFx0XHQvLyBPdGhlcndpc2Ugd2UgbmVlZCB0byBnZXQgYSBwcm9wZXIgY29weVxuXHRcdFx0cmV0dXJuIGJ1Zi5idWZmZXIuc2xpY2UoYnVmLmJ5dGVPZmZzZXQsIGJ1Zi5ieXRlT2Zmc2V0ICsgYnVmLmJ5dGVMZW5ndGgpXG5cdFx0fVxuXHR9XG5cblx0aWYgKEJ1ZmZlci5pc0J1ZmZlcihidWYpKSB7XG5cdFx0Ly8gVGhpcyBpcyB0aGUgc2xvdyB2ZXJzaW9uIHRoYXQgd2lsbCB3b3JrIHdpdGggYW55IEJ1ZmZlclxuXHRcdC8vIGltcGxlbWVudGF0aW9uIChldmVuIGluIG9sZCBicm93c2Vycylcblx0XHR2YXIgYXJyYXlDb3B5ID0gbmV3IFVpbnQ4QXJyYXkoYnVmLmxlbmd0aClcblx0XHR2YXIgbGVuID0gYnVmLmxlbmd0aFxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdGFycmF5Q29weVtpXSA9IGJ1ZltpXVxuXHRcdH1cblx0XHRyZXR1cm4gYXJyYXlDb3B5LmJ1ZmZlclxuXHR9IGVsc2Uge1xuXHRcdHRocm93IG5ldyBFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlcicpXG5cdH1cbn1cbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4ndXNlIHN0cmljdCc7XG5cbnZhciBwdW55Y29kZSA9IHJlcXVpcmUoJ3B1bnljb2RlJyk7XG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xuXG5leHBvcnRzLnBhcnNlID0gdXJsUGFyc2U7XG5leHBvcnRzLnJlc29sdmUgPSB1cmxSZXNvbHZlO1xuZXhwb3J0cy5yZXNvbHZlT2JqZWN0ID0gdXJsUmVzb2x2ZU9iamVjdDtcbmV4cG9ydHMuZm9ybWF0ID0gdXJsRm9ybWF0O1xuXG5leHBvcnRzLlVybCA9IFVybDtcblxuZnVuY3Rpb24gVXJsKCkge1xuICB0aGlzLnByb3RvY29sID0gbnVsbDtcbiAgdGhpcy5zbGFzaGVzID0gbnVsbDtcbiAgdGhpcy5hdXRoID0gbnVsbDtcbiAgdGhpcy5ob3N0ID0gbnVsbDtcbiAgdGhpcy5wb3J0ID0gbnVsbDtcbiAgdGhpcy5ob3N0bmFtZSA9IG51bGw7XG4gIHRoaXMuaGFzaCA9IG51bGw7XG4gIHRoaXMuc2VhcmNoID0gbnVsbDtcbiAgdGhpcy5xdWVyeSA9IG51bGw7XG4gIHRoaXMucGF0aG5hbWUgPSBudWxsO1xuICB0aGlzLnBhdGggPSBudWxsO1xuICB0aGlzLmhyZWYgPSBudWxsO1xufVxuXG4vLyBSZWZlcmVuY2U6IFJGQyAzOTg2LCBSRkMgMTgwOCwgUkZDIDIzOTZcblxuLy8gZGVmaW5lIHRoZXNlIGhlcmUgc28gYXQgbGVhc3QgdGhleSBvbmx5IGhhdmUgdG8gYmVcbi8vIGNvbXBpbGVkIG9uY2Ugb24gdGhlIGZpcnN0IG1vZHVsZSBsb2FkLlxudmFyIHByb3RvY29sUGF0dGVybiA9IC9eKFthLXowLTkuKy1dKzopL2ksXG4gICAgcG9ydFBhdHRlcm4gPSAvOlswLTldKiQvLFxuXG4gICAgLy8gU3BlY2lhbCBjYXNlIGZvciBhIHNpbXBsZSBwYXRoIFVSTFxuICAgIHNpbXBsZVBhdGhQYXR0ZXJuID0gL14oXFwvXFwvPyg/IVxcLylbXlxcP1xcc10qKShcXD9bXlxcc10qKT8kLyxcblxuICAgIC8vIFJGQyAyMzk2OiBjaGFyYWN0ZXJzIHJlc2VydmVkIGZvciBkZWxpbWl0aW5nIFVSTHMuXG4gICAgLy8gV2UgYWN0dWFsbHkganVzdCBhdXRvLWVzY2FwZSB0aGVzZS5cbiAgICBkZWxpbXMgPSBbJzwnLCAnPicsICdcIicsICdgJywgJyAnLCAnXFxyJywgJ1xcbicsICdcXHQnXSxcblxuICAgIC8vIFJGQyAyMzk2OiBjaGFyYWN0ZXJzIG5vdCBhbGxvd2VkIGZvciB2YXJpb3VzIHJlYXNvbnMuXG4gICAgdW53aXNlID0gWyd7JywgJ30nLCAnfCcsICdcXFxcJywgJ14nLCAnYCddLmNvbmNhdChkZWxpbXMpLFxuXG4gICAgLy8gQWxsb3dlZCBieSBSRkNzLCBidXQgY2F1c2Ugb2YgWFNTIGF0dGFja3MuICBBbHdheXMgZXNjYXBlIHRoZXNlLlxuICAgIGF1dG9Fc2NhcGUgPSBbJ1xcJyddLmNvbmNhdCh1bndpc2UpLFxuICAgIC8vIENoYXJhY3RlcnMgdGhhdCBhcmUgbmV2ZXIgZXZlciBhbGxvd2VkIGluIGEgaG9zdG5hbWUuXG4gICAgLy8gTm90ZSB0aGF0IGFueSBpbnZhbGlkIGNoYXJzIGFyZSBhbHNvIGhhbmRsZWQsIGJ1dCB0aGVzZVxuICAgIC8vIGFyZSB0aGUgb25lcyB0aGF0IGFyZSAqZXhwZWN0ZWQqIHRvIGJlIHNlZW4sIHNvIHdlIGZhc3QtcGF0aFxuICAgIC8vIHRoZW0uXG4gICAgbm9uSG9zdENoYXJzID0gWyclJywgJy8nLCAnPycsICc7JywgJyMnXS5jb25jYXQoYXV0b0VzY2FwZSksXG4gICAgaG9zdEVuZGluZ0NoYXJzID0gWycvJywgJz8nLCAnIyddLFxuICAgIGhvc3RuYW1lTWF4TGVuID0gMjU1LFxuICAgIGhvc3RuYW1lUGFydFBhdHRlcm4gPSAvXlsrYS16MC05QS1aXy1dezAsNjN9JC8sXG4gICAgaG9zdG5hbWVQYXJ0U3RhcnQgPSAvXihbK2EtejAtOUEtWl8tXXswLDYzfSkoLiopJC8sXG4gICAgLy8gcHJvdG9jb2xzIHRoYXQgY2FuIGFsbG93IFwidW5zYWZlXCIgYW5kIFwidW53aXNlXCIgY2hhcnMuXG4gICAgdW5zYWZlUHJvdG9jb2wgPSB7XG4gICAgICAnamF2YXNjcmlwdCc6IHRydWUsXG4gICAgICAnamF2YXNjcmlwdDonOiB0cnVlXG4gICAgfSxcbiAgICAvLyBwcm90b2NvbHMgdGhhdCBuZXZlciBoYXZlIGEgaG9zdG5hbWUuXG4gICAgaG9zdGxlc3NQcm90b2NvbCA9IHtcbiAgICAgICdqYXZhc2NyaXB0JzogdHJ1ZSxcbiAgICAgICdqYXZhc2NyaXB0Oic6IHRydWVcbiAgICB9LFxuICAgIC8vIHByb3RvY29scyB0aGF0IGFsd2F5cyBjb250YWluIGEgLy8gYml0LlxuICAgIHNsYXNoZWRQcm90b2NvbCA9IHtcbiAgICAgICdodHRwJzogdHJ1ZSxcbiAgICAgICdodHRwcyc6IHRydWUsXG4gICAgICAnZnRwJzogdHJ1ZSxcbiAgICAgICdnb3BoZXInOiB0cnVlLFxuICAgICAgJ2ZpbGUnOiB0cnVlLFxuICAgICAgJ2h0dHA6JzogdHJ1ZSxcbiAgICAgICdodHRwczonOiB0cnVlLFxuICAgICAgJ2Z0cDonOiB0cnVlLFxuICAgICAgJ2dvcGhlcjonOiB0cnVlLFxuICAgICAgJ2ZpbGU6JzogdHJ1ZVxuICAgIH0sXG4gICAgcXVlcnlzdHJpbmcgPSByZXF1aXJlKCdxdWVyeXN0cmluZycpO1xuXG5mdW5jdGlvbiB1cmxQYXJzZSh1cmwsIHBhcnNlUXVlcnlTdHJpbmcsIHNsYXNoZXNEZW5vdGVIb3N0KSB7XG4gIGlmICh1cmwgJiYgdXRpbC5pc09iamVjdCh1cmwpICYmIHVybCBpbnN0YW5jZW9mIFVybCkgcmV0dXJuIHVybDtcblxuICB2YXIgdSA9IG5ldyBVcmw7XG4gIHUucGFyc2UodXJsLCBwYXJzZVF1ZXJ5U3RyaW5nLCBzbGFzaGVzRGVub3RlSG9zdCk7XG4gIHJldHVybiB1O1xufVxuXG5VcmwucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24odXJsLCBwYXJzZVF1ZXJ5U3RyaW5nLCBzbGFzaGVzRGVub3RlSG9zdCkge1xuICBpZiAoIXV0aWwuaXNTdHJpbmcodXJsKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQYXJhbWV0ZXIgJ3VybCcgbXVzdCBiZSBhIHN0cmluZywgbm90IFwiICsgdHlwZW9mIHVybCk7XG4gIH1cblxuICAvLyBDb3B5IGNocm9tZSwgSUUsIG9wZXJhIGJhY2tzbGFzaC1oYW5kbGluZyBiZWhhdmlvci5cbiAgLy8gQmFjayBzbGFzaGVzIGJlZm9yZSB0aGUgcXVlcnkgc3RyaW5nIGdldCBjb252ZXJ0ZWQgdG8gZm9yd2FyZCBzbGFzaGVzXG4gIC8vIFNlZTogaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTI1OTE2XG4gIHZhciBxdWVyeUluZGV4ID0gdXJsLmluZGV4T2YoJz8nKSxcbiAgICAgIHNwbGl0dGVyID1cbiAgICAgICAgICAocXVlcnlJbmRleCAhPT0gLTEgJiYgcXVlcnlJbmRleCA8IHVybC5pbmRleE9mKCcjJykpID8gJz8nIDogJyMnLFxuICAgICAgdVNwbGl0ID0gdXJsLnNwbGl0KHNwbGl0dGVyKSxcbiAgICAgIHNsYXNoUmVnZXggPSAvXFxcXC9nO1xuICB1U3BsaXRbMF0gPSB1U3BsaXRbMF0ucmVwbGFjZShzbGFzaFJlZ2V4LCAnLycpO1xuICB1cmwgPSB1U3BsaXQuam9pbihzcGxpdHRlcik7XG5cbiAgdmFyIHJlc3QgPSB1cmw7XG5cbiAgLy8gdHJpbSBiZWZvcmUgcHJvY2VlZGluZy5cbiAgLy8gVGhpcyBpcyB0byBzdXBwb3J0IHBhcnNlIHN0dWZmIGxpa2UgXCIgIGh0dHA6Ly9mb28uY29tICBcXG5cIlxuICByZXN0ID0gcmVzdC50cmltKCk7XG5cbiAgaWYgKCFzbGFzaGVzRGVub3RlSG9zdCAmJiB1cmwuc3BsaXQoJyMnKS5sZW5ndGggPT09IDEpIHtcbiAgICAvLyBUcnkgZmFzdCBwYXRoIHJlZ2V4cFxuICAgIHZhciBzaW1wbGVQYXRoID0gc2ltcGxlUGF0aFBhdHRlcm4uZXhlYyhyZXN0KTtcbiAgICBpZiAoc2ltcGxlUGF0aCkge1xuICAgICAgdGhpcy5wYXRoID0gcmVzdDtcbiAgICAgIHRoaXMuaHJlZiA9IHJlc3Q7XG4gICAgICB0aGlzLnBhdGhuYW1lID0gc2ltcGxlUGF0aFsxXTtcbiAgICAgIGlmIChzaW1wbGVQYXRoWzJdKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoID0gc2ltcGxlUGF0aFsyXTtcbiAgICAgICAgaWYgKHBhcnNlUXVlcnlTdHJpbmcpIHtcbiAgICAgICAgICB0aGlzLnF1ZXJ5ID0gcXVlcnlzdHJpbmcucGFyc2UodGhpcy5zZWFyY2guc3Vic3RyKDEpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnF1ZXJ5ID0gdGhpcy5zZWFyY2guc3Vic3RyKDEpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHBhcnNlUXVlcnlTdHJpbmcpIHtcbiAgICAgICAgdGhpcy5zZWFyY2ggPSAnJztcbiAgICAgICAgdGhpcy5xdWVyeSA9IHt9O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICB9XG5cbiAgdmFyIHByb3RvID0gcHJvdG9jb2xQYXR0ZXJuLmV4ZWMocmVzdCk7XG4gIGlmIChwcm90bykge1xuICAgIHByb3RvID0gcHJvdG9bMF07XG4gICAgdmFyIGxvd2VyUHJvdG8gPSBwcm90by50b0xvd2VyQ2FzZSgpO1xuICAgIHRoaXMucHJvdG9jb2wgPSBsb3dlclByb3RvO1xuICAgIHJlc3QgPSByZXN0LnN1YnN0cihwcm90by5sZW5ndGgpO1xuICB9XG5cbiAgLy8gZmlndXJlIG91dCBpZiBpdCdzIGdvdCBhIGhvc3RcbiAgLy8gdXNlckBzZXJ2ZXIgaXMgKmFsd2F5cyogaW50ZXJwcmV0ZWQgYXMgYSBob3N0bmFtZSwgYW5kIHVybFxuICAvLyByZXNvbHV0aW9uIHdpbGwgdHJlYXQgLy9mb28vYmFyIGFzIGhvc3Q9Zm9vLHBhdGg9YmFyIGJlY2F1c2UgdGhhdCdzXG4gIC8vIGhvdyB0aGUgYnJvd3NlciByZXNvbHZlcyByZWxhdGl2ZSBVUkxzLlxuICBpZiAoc2xhc2hlc0Rlbm90ZUhvc3QgfHwgcHJvdG8gfHwgcmVzdC5tYXRjaCgvXlxcL1xcL1teQFxcL10rQFteQFxcL10rLykpIHtcbiAgICB2YXIgc2xhc2hlcyA9IHJlc3Quc3Vic3RyKDAsIDIpID09PSAnLy8nO1xuICAgIGlmIChzbGFzaGVzICYmICEocHJvdG8gJiYgaG9zdGxlc3NQcm90b2NvbFtwcm90b10pKSB7XG4gICAgICByZXN0ID0gcmVzdC5zdWJzdHIoMik7XG4gICAgICB0aGlzLnNsYXNoZXMgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICghaG9zdGxlc3NQcm90b2NvbFtwcm90b10gJiZcbiAgICAgIChzbGFzaGVzIHx8IChwcm90byAmJiAhc2xhc2hlZFByb3RvY29sW3Byb3RvXSkpKSB7XG5cbiAgICAvLyB0aGVyZSdzIGEgaG9zdG5hbWUuXG4gICAgLy8gdGhlIGZpcnN0IGluc3RhbmNlIG9mIC8sID8sIDssIG9yICMgZW5kcyB0aGUgaG9zdC5cbiAgICAvL1xuICAgIC8vIElmIHRoZXJlIGlzIGFuIEAgaW4gdGhlIGhvc3RuYW1lLCB0aGVuIG5vbi1ob3N0IGNoYXJzICphcmUqIGFsbG93ZWRcbiAgICAvLyB0byB0aGUgbGVmdCBvZiB0aGUgbGFzdCBAIHNpZ24sIHVubGVzcyBzb21lIGhvc3QtZW5kaW5nIGNoYXJhY3RlclxuICAgIC8vIGNvbWVzICpiZWZvcmUqIHRoZSBALXNpZ24uXG4gICAgLy8gVVJMcyBhcmUgb2Jub3hpb3VzLlxuICAgIC8vXG4gICAgLy8gZXg6XG4gICAgLy8gaHR0cDovL2FAYkBjLyA9PiB1c2VyOmFAYiBob3N0OmNcbiAgICAvLyBodHRwOi8vYUBiP0BjID0+IHVzZXI6YSBob3N0OmMgcGF0aDovP0BjXG5cbiAgICAvLyB2MC4xMiBUT0RPKGlzYWFjcyk6IFRoaXMgaXMgbm90IHF1aXRlIGhvdyBDaHJvbWUgZG9lcyB0aGluZ3MuXG4gICAgLy8gUmV2aWV3IG91ciB0ZXN0IGNhc2UgYWdhaW5zdCBicm93c2VycyBtb3JlIGNvbXByZWhlbnNpdmVseS5cblxuICAgIC8vIGZpbmQgdGhlIGZpcnN0IGluc3RhbmNlIG9mIGFueSBob3N0RW5kaW5nQ2hhcnNcbiAgICB2YXIgaG9zdEVuZCA9IC0xO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaG9zdEVuZGluZ0NoYXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaGVjID0gcmVzdC5pbmRleE9mKGhvc3RFbmRpbmdDaGFyc1tpXSk7XG4gICAgICBpZiAoaGVjICE9PSAtMSAmJiAoaG9zdEVuZCA9PT0gLTEgfHwgaGVjIDwgaG9zdEVuZCkpXG4gICAgICAgIGhvc3RFbmQgPSBoZWM7XG4gICAgfVxuXG4gICAgLy8gYXQgdGhpcyBwb2ludCwgZWl0aGVyIHdlIGhhdmUgYW4gZXhwbGljaXQgcG9pbnQgd2hlcmUgdGhlXG4gICAgLy8gYXV0aCBwb3J0aW9uIGNhbm5vdCBnbyBwYXN0LCBvciB0aGUgbGFzdCBAIGNoYXIgaXMgdGhlIGRlY2lkZXIuXG4gICAgdmFyIGF1dGgsIGF0U2lnbjtcbiAgICBpZiAoaG9zdEVuZCA9PT0gLTEpIHtcbiAgICAgIC8vIGF0U2lnbiBjYW4gYmUgYW55d2hlcmUuXG4gICAgICBhdFNpZ24gPSByZXN0Lmxhc3RJbmRleE9mKCdAJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGF0U2lnbiBtdXN0IGJlIGluIGF1dGggcG9ydGlvbi5cbiAgICAgIC8vIGh0dHA6Ly9hQGIvY0BkID0+IGhvc3Q6YiBhdXRoOmEgcGF0aDovY0BkXG4gICAgICBhdFNpZ24gPSByZXN0Lmxhc3RJbmRleE9mKCdAJywgaG9zdEVuZCk7XG4gICAgfVxuXG4gICAgLy8gTm93IHdlIGhhdmUgYSBwb3J0aW9uIHdoaWNoIGlzIGRlZmluaXRlbHkgdGhlIGF1dGguXG4gICAgLy8gUHVsbCB0aGF0IG9mZi5cbiAgICBpZiAoYXRTaWduICE9PSAtMSkge1xuICAgICAgYXV0aCA9IHJlc3Quc2xpY2UoMCwgYXRTaWduKTtcbiAgICAgIHJlc3QgPSByZXN0LnNsaWNlKGF0U2lnbiArIDEpO1xuICAgICAgdGhpcy5hdXRoID0gZGVjb2RlVVJJQ29tcG9uZW50KGF1dGgpO1xuICAgIH1cblxuICAgIC8vIHRoZSBob3N0IGlzIHRoZSByZW1haW5pbmcgdG8gdGhlIGxlZnQgb2YgdGhlIGZpcnN0IG5vbi1ob3N0IGNoYXJcbiAgICBob3N0RW5kID0gLTE7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBub25Ib3N0Q2hhcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBoZWMgPSByZXN0LmluZGV4T2Yobm9uSG9zdENoYXJzW2ldKTtcbiAgICAgIGlmIChoZWMgIT09IC0xICYmIChob3N0RW5kID09PSAtMSB8fCBoZWMgPCBob3N0RW5kKSlcbiAgICAgICAgaG9zdEVuZCA9IGhlYztcbiAgICB9XG4gICAgLy8gaWYgd2Ugc3RpbGwgaGF2ZSBub3QgaGl0IGl0LCB0aGVuIHRoZSBlbnRpcmUgdGhpbmcgaXMgYSBob3N0LlxuICAgIGlmIChob3N0RW5kID09PSAtMSlcbiAgICAgIGhvc3RFbmQgPSByZXN0Lmxlbmd0aDtcblxuICAgIHRoaXMuaG9zdCA9IHJlc3Quc2xpY2UoMCwgaG9zdEVuZCk7XG4gICAgcmVzdCA9IHJlc3Quc2xpY2UoaG9zdEVuZCk7XG5cbiAgICAvLyBwdWxsIG91dCBwb3J0LlxuICAgIHRoaXMucGFyc2VIb3N0KCk7XG5cbiAgICAvLyB3ZSd2ZSBpbmRpY2F0ZWQgdGhhdCB0aGVyZSBpcyBhIGhvc3RuYW1lLFxuICAgIC8vIHNvIGV2ZW4gaWYgaXQncyBlbXB0eSwgaXQgaGFzIHRvIGJlIHByZXNlbnQuXG4gICAgdGhpcy5ob3N0bmFtZSA9IHRoaXMuaG9zdG5hbWUgfHwgJyc7XG5cbiAgICAvLyBpZiBob3N0bmFtZSBiZWdpbnMgd2l0aCBbIGFuZCBlbmRzIHdpdGggXVxuICAgIC8vIGFzc3VtZSB0aGF0IGl0J3MgYW4gSVB2NiBhZGRyZXNzLlxuICAgIHZhciBpcHY2SG9zdG5hbWUgPSB0aGlzLmhvc3RuYW1lWzBdID09PSAnWycgJiZcbiAgICAgICAgdGhpcy5ob3N0bmFtZVt0aGlzLmhvc3RuYW1lLmxlbmd0aCAtIDFdID09PSAnXSc7XG5cbiAgICAvLyB2YWxpZGF0ZSBhIGxpdHRsZS5cbiAgICBpZiAoIWlwdjZIb3N0bmFtZSkge1xuICAgICAgdmFyIGhvc3RwYXJ0cyA9IHRoaXMuaG9zdG5hbWUuc3BsaXQoL1xcLi8pO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBob3N0cGFydHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIHZhciBwYXJ0ID0gaG9zdHBhcnRzW2ldO1xuICAgICAgICBpZiAoIXBhcnQpIGNvbnRpbnVlO1xuICAgICAgICBpZiAoIXBhcnQubWF0Y2goaG9zdG5hbWVQYXJ0UGF0dGVybikpIHtcbiAgICAgICAgICB2YXIgbmV3cGFydCA9ICcnO1xuICAgICAgICAgIGZvciAodmFyIGogPSAwLCBrID0gcGFydC5sZW5ndGg7IGogPCBrOyBqKyspIHtcbiAgICAgICAgICAgIGlmIChwYXJ0LmNoYXJDb2RlQXQoaikgPiAxMjcpIHtcbiAgICAgICAgICAgICAgLy8gd2UgcmVwbGFjZSBub24tQVNDSUkgY2hhciB3aXRoIGEgdGVtcG9yYXJ5IHBsYWNlaG9sZGVyXG4gICAgICAgICAgICAgIC8vIHdlIG5lZWQgdGhpcyB0byBtYWtlIHN1cmUgc2l6ZSBvZiBob3N0bmFtZSBpcyBub3RcbiAgICAgICAgICAgICAgLy8gYnJva2VuIGJ5IHJlcGxhY2luZyBub24tQVNDSUkgYnkgbm90aGluZ1xuICAgICAgICAgICAgICBuZXdwYXJ0ICs9ICd4JztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIG5ld3BhcnQgKz0gcGFydFtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gd2UgdGVzdCBhZ2FpbiB3aXRoIEFTQ0lJIGNoYXIgb25seVxuICAgICAgICAgIGlmICghbmV3cGFydC5tYXRjaChob3N0bmFtZVBhcnRQYXR0ZXJuKSkge1xuICAgICAgICAgICAgdmFyIHZhbGlkUGFydHMgPSBob3N0cGFydHMuc2xpY2UoMCwgaSk7XG4gICAgICAgICAgICB2YXIgbm90SG9zdCA9IGhvc3RwYXJ0cy5zbGljZShpICsgMSk7XG4gICAgICAgICAgICB2YXIgYml0ID0gcGFydC5tYXRjaChob3N0bmFtZVBhcnRTdGFydCk7XG4gICAgICAgICAgICBpZiAoYml0KSB7XG4gICAgICAgICAgICAgIHZhbGlkUGFydHMucHVzaChiaXRbMV0pO1xuICAgICAgICAgICAgICBub3RIb3N0LnVuc2hpZnQoYml0WzJdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub3RIb3N0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICByZXN0ID0gJy8nICsgbm90SG9zdC5qb2luKCcuJykgKyByZXN0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5ob3N0bmFtZSA9IHZhbGlkUGFydHMuam9pbignLicpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaG9zdG5hbWUubGVuZ3RoID4gaG9zdG5hbWVNYXhMZW4pIHtcbiAgICAgIHRoaXMuaG9zdG5hbWUgPSAnJztcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaG9zdG5hbWVzIGFyZSBhbHdheXMgbG93ZXIgY2FzZS5cbiAgICAgIHRoaXMuaG9zdG5hbWUgPSB0aGlzLmhvc3RuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuXG4gICAgaWYgKCFpcHY2SG9zdG5hbWUpIHtcbiAgICAgIC8vIElETkEgU3VwcG9ydDogUmV0dXJucyBhIHB1bnljb2RlZCByZXByZXNlbnRhdGlvbiBvZiBcImRvbWFpblwiLlxuICAgICAgLy8gSXQgb25seSBjb252ZXJ0cyBwYXJ0cyBvZiB0aGUgZG9tYWluIG5hbWUgdGhhdFxuICAgICAgLy8gaGF2ZSBub24tQVNDSUkgY2hhcmFjdGVycywgaS5lLiBpdCBkb2Vzbid0IG1hdHRlciBpZlxuICAgICAgLy8geW91IGNhbGwgaXQgd2l0aCBhIGRvbWFpbiB0aGF0IGFscmVhZHkgaXMgQVNDSUktb25seS5cbiAgICAgIHRoaXMuaG9zdG5hbWUgPSBwdW55Y29kZS50b0FTQ0lJKHRoaXMuaG9zdG5hbWUpO1xuICAgIH1cblxuICAgIHZhciBwID0gdGhpcy5wb3J0ID8gJzonICsgdGhpcy5wb3J0IDogJyc7XG4gICAgdmFyIGggPSB0aGlzLmhvc3RuYW1lIHx8ICcnO1xuICAgIHRoaXMuaG9zdCA9IGggKyBwO1xuICAgIHRoaXMuaHJlZiArPSB0aGlzLmhvc3Q7XG5cbiAgICAvLyBzdHJpcCBbIGFuZCBdIGZyb20gdGhlIGhvc3RuYW1lXG4gICAgLy8gdGhlIGhvc3QgZmllbGQgc3RpbGwgcmV0YWlucyB0aGVtLCB0aG91Z2hcbiAgICBpZiAoaXB2Nkhvc3RuYW1lKSB7XG4gICAgICB0aGlzLmhvc3RuYW1lID0gdGhpcy5ob3N0bmFtZS5zdWJzdHIoMSwgdGhpcy5ob3N0bmFtZS5sZW5ndGggLSAyKTtcbiAgICAgIGlmIChyZXN0WzBdICE9PSAnLycpIHtcbiAgICAgICAgcmVzdCA9ICcvJyArIHJlc3Q7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gbm93IHJlc3QgaXMgc2V0IHRvIHRoZSBwb3N0LWhvc3Qgc3R1ZmYuXG4gIC8vIGNob3Agb2ZmIGFueSBkZWxpbSBjaGFycy5cbiAgaWYgKCF1bnNhZmVQcm90b2NvbFtsb3dlclByb3RvXSkge1xuXG4gICAgLy8gRmlyc3QsIG1ha2UgMTAwJSBzdXJlIHRoYXQgYW55IFwiYXV0b0VzY2FwZVwiIGNoYXJzIGdldFxuICAgIC8vIGVzY2FwZWQsIGV2ZW4gaWYgZW5jb2RlVVJJQ29tcG9uZW50IGRvZXNuJ3QgdGhpbmsgdGhleVxuICAgIC8vIG5lZWQgdG8gYmUuXG4gICAgZm9yICh2YXIgaSA9IDAsIGwgPSBhdXRvRXNjYXBlLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgdmFyIGFlID0gYXV0b0VzY2FwZVtpXTtcbiAgICAgIGlmIChyZXN0LmluZGV4T2YoYWUpID09PSAtMSlcbiAgICAgICAgY29udGludWU7XG4gICAgICB2YXIgZXNjID0gZW5jb2RlVVJJQ29tcG9uZW50KGFlKTtcbiAgICAgIGlmIChlc2MgPT09IGFlKSB7XG4gICAgICAgIGVzYyA9IGVzY2FwZShhZSk7XG4gICAgICB9XG4gICAgICByZXN0ID0gcmVzdC5zcGxpdChhZSkuam9pbihlc2MpO1xuICAgIH1cbiAgfVxuXG5cbiAgLy8gY2hvcCBvZmYgZnJvbSB0aGUgdGFpbCBmaXJzdC5cbiAgdmFyIGhhc2ggPSByZXN0LmluZGV4T2YoJyMnKTtcbiAgaWYgKGhhc2ggIT09IC0xKSB7XG4gICAgLy8gZ290IGEgZnJhZ21lbnQgc3RyaW5nLlxuICAgIHRoaXMuaGFzaCA9IHJlc3Quc3Vic3RyKGhhc2gpO1xuICAgIHJlc3QgPSByZXN0LnNsaWNlKDAsIGhhc2gpO1xuICB9XG4gIHZhciBxbSA9IHJlc3QuaW5kZXhPZignPycpO1xuICBpZiAocW0gIT09IC0xKSB7XG4gICAgdGhpcy5zZWFyY2ggPSByZXN0LnN1YnN0cihxbSk7XG4gICAgdGhpcy5xdWVyeSA9IHJlc3Quc3Vic3RyKHFtICsgMSk7XG4gICAgaWYgKHBhcnNlUXVlcnlTdHJpbmcpIHtcbiAgICAgIHRoaXMucXVlcnkgPSBxdWVyeXN0cmluZy5wYXJzZSh0aGlzLnF1ZXJ5KTtcbiAgICB9XG4gICAgcmVzdCA9IHJlc3Quc2xpY2UoMCwgcW0pO1xuICB9IGVsc2UgaWYgKHBhcnNlUXVlcnlTdHJpbmcpIHtcbiAgICAvLyBubyBxdWVyeSBzdHJpbmcsIGJ1dCBwYXJzZVF1ZXJ5U3RyaW5nIHN0aWxsIHJlcXVlc3RlZFxuICAgIHRoaXMuc2VhcmNoID0gJyc7XG4gICAgdGhpcy5xdWVyeSA9IHt9O1xuICB9XG4gIGlmIChyZXN0KSB0aGlzLnBhdGhuYW1lID0gcmVzdDtcbiAgaWYgKHNsYXNoZWRQcm90b2NvbFtsb3dlclByb3RvXSAmJlxuICAgICAgdGhpcy5ob3N0bmFtZSAmJiAhdGhpcy5wYXRobmFtZSkge1xuICAgIHRoaXMucGF0aG5hbWUgPSAnLyc7XG4gIH1cblxuICAvL3RvIHN1cHBvcnQgaHR0cC5yZXF1ZXN0XG4gIGlmICh0aGlzLnBhdGhuYW1lIHx8IHRoaXMuc2VhcmNoKSB7XG4gICAgdmFyIHAgPSB0aGlzLnBhdGhuYW1lIHx8ICcnO1xuICAgIHZhciBzID0gdGhpcy5zZWFyY2ggfHwgJyc7XG4gICAgdGhpcy5wYXRoID0gcCArIHM7XG4gIH1cblxuICAvLyBmaW5hbGx5LCByZWNvbnN0cnVjdCB0aGUgaHJlZiBiYXNlZCBvbiB3aGF0IGhhcyBiZWVuIHZhbGlkYXRlZC5cbiAgdGhpcy5ocmVmID0gdGhpcy5mb3JtYXQoKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBmb3JtYXQgYSBwYXJzZWQgb2JqZWN0IGludG8gYSB1cmwgc3RyaW5nXG5mdW5jdGlvbiB1cmxGb3JtYXQob2JqKSB7XG4gIC8vIGVuc3VyZSBpdCdzIGFuIG9iamVjdCwgYW5kIG5vdCBhIHN0cmluZyB1cmwuXG4gIC8vIElmIGl0J3MgYW4gb2JqLCB0aGlzIGlzIGEgbm8tb3AuXG4gIC8vIHRoaXMgd2F5LCB5b3UgY2FuIGNhbGwgdXJsX2Zvcm1hdCgpIG9uIHN0cmluZ3NcbiAgLy8gdG8gY2xlYW4gdXAgcG90ZW50aWFsbHkgd29ua3kgdXJscy5cbiAgaWYgKHV0aWwuaXNTdHJpbmcob2JqKSkgb2JqID0gdXJsUGFyc2Uob2JqKTtcbiAgaWYgKCEob2JqIGluc3RhbmNlb2YgVXJsKSkgcmV0dXJuIFVybC5wcm90b3R5cGUuZm9ybWF0LmNhbGwob2JqKTtcbiAgcmV0dXJuIG9iai5mb3JtYXQoKTtcbn1cblxuVXJsLnByb3RvdHlwZS5mb3JtYXQgPSBmdW5jdGlvbigpIHtcbiAgdmFyIGF1dGggPSB0aGlzLmF1dGggfHwgJyc7XG4gIGlmIChhdXRoKSB7XG4gICAgYXV0aCA9IGVuY29kZVVSSUNvbXBvbmVudChhdXRoKTtcbiAgICBhdXRoID0gYXV0aC5yZXBsYWNlKC8lM0EvaSwgJzonKTtcbiAgICBhdXRoICs9ICdAJztcbiAgfVxuXG4gIHZhciBwcm90b2NvbCA9IHRoaXMucHJvdG9jb2wgfHwgJycsXG4gICAgICBwYXRobmFtZSA9IHRoaXMucGF0aG5hbWUgfHwgJycsXG4gICAgICBoYXNoID0gdGhpcy5oYXNoIHx8ICcnLFxuICAgICAgaG9zdCA9IGZhbHNlLFxuICAgICAgcXVlcnkgPSAnJztcblxuICBpZiAodGhpcy5ob3N0KSB7XG4gICAgaG9zdCA9IGF1dGggKyB0aGlzLmhvc3Q7XG4gIH0gZWxzZSBpZiAodGhpcy5ob3N0bmFtZSkge1xuICAgIGhvc3QgPSBhdXRoICsgKHRoaXMuaG9zdG5hbWUuaW5kZXhPZignOicpID09PSAtMSA/XG4gICAgICAgIHRoaXMuaG9zdG5hbWUgOlxuICAgICAgICAnWycgKyB0aGlzLmhvc3RuYW1lICsgJ10nKTtcbiAgICBpZiAodGhpcy5wb3J0KSB7XG4gICAgICBob3N0ICs9ICc6JyArIHRoaXMucG9ydDtcbiAgICB9XG4gIH1cblxuICBpZiAodGhpcy5xdWVyeSAmJlxuICAgICAgdXRpbC5pc09iamVjdCh0aGlzLnF1ZXJ5KSAmJlxuICAgICAgT2JqZWN0LmtleXModGhpcy5xdWVyeSkubGVuZ3RoKSB7XG4gICAgcXVlcnkgPSBxdWVyeXN0cmluZy5zdHJpbmdpZnkodGhpcy5xdWVyeSk7XG4gIH1cblxuICB2YXIgc2VhcmNoID0gdGhpcy5zZWFyY2ggfHwgKHF1ZXJ5ICYmICgnPycgKyBxdWVyeSkpIHx8ICcnO1xuXG4gIGlmIChwcm90b2NvbCAmJiBwcm90b2NvbC5zdWJzdHIoLTEpICE9PSAnOicpIHByb3RvY29sICs9ICc6JztcblxuICAvLyBvbmx5IHRoZSBzbGFzaGVkUHJvdG9jb2xzIGdldCB0aGUgLy8uICBOb3QgbWFpbHRvOiwgeG1wcDosIGV0Yy5cbiAgLy8gdW5sZXNzIHRoZXkgaGFkIHRoZW0gdG8gYmVnaW4gd2l0aC5cbiAgaWYgKHRoaXMuc2xhc2hlcyB8fFxuICAgICAgKCFwcm90b2NvbCB8fCBzbGFzaGVkUHJvdG9jb2xbcHJvdG9jb2xdKSAmJiBob3N0ICE9PSBmYWxzZSkge1xuICAgIGhvc3QgPSAnLy8nICsgKGhvc3QgfHwgJycpO1xuICAgIGlmIChwYXRobmFtZSAmJiBwYXRobmFtZS5jaGFyQXQoMCkgIT09ICcvJykgcGF0aG5hbWUgPSAnLycgKyBwYXRobmFtZTtcbiAgfSBlbHNlIGlmICghaG9zdCkge1xuICAgIGhvc3QgPSAnJztcbiAgfVxuXG4gIGlmIChoYXNoICYmIGhhc2guY2hhckF0KDApICE9PSAnIycpIGhhc2ggPSAnIycgKyBoYXNoO1xuICBpZiAoc2VhcmNoICYmIHNlYXJjaC5jaGFyQXQoMCkgIT09ICc/Jykgc2VhcmNoID0gJz8nICsgc2VhcmNoO1xuXG4gIHBhdGhuYW1lID0gcGF0aG5hbWUucmVwbGFjZSgvWz8jXS9nLCBmdW5jdGlvbihtYXRjaCkge1xuICAgIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQobWF0Y2gpO1xuICB9KTtcbiAgc2VhcmNoID0gc2VhcmNoLnJlcGxhY2UoJyMnLCAnJTIzJyk7XG5cbiAgcmV0dXJuIHByb3RvY29sICsgaG9zdCArIHBhdGhuYW1lICsgc2VhcmNoICsgaGFzaDtcbn07XG5cbmZ1bmN0aW9uIHVybFJlc29sdmUoc291cmNlLCByZWxhdGl2ZSkge1xuICByZXR1cm4gdXJsUGFyc2Uoc291cmNlLCBmYWxzZSwgdHJ1ZSkucmVzb2x2ZShyZWxhdGl2ZSk7XG59XG5cblVybC5wcm90b3R5cGUucmVzb2x2ZSA9IGZ1bmN0aW9uKHJlbGF0aXZlKSB7XG4gIHJldHVybiB0aGlzLnJlc29sdmVPYmplY3QodXJsUGFyc2UocmVsYXRpdmUsIGZhbHNlLCB0cnVlKSkuZm9ybWF0KCk7XG59O1xuXG5mdW5jdGlvbiB1cmxSZXNvbHZlT2JqZWN0KHNvdXJjZSwgcmVsYXRpdmUpIHtcbiAgaWYgKCFzb3VyY2UpIHJldHVybiByZWxhdGl2ZTtcbiAgcmV0dXJuIHVybFBhcnNlKHNvdXJjZSwgZmFsc2UsIHRydWUpLnJlc29sdmVPYmplY3QocmVsYXRpdmUpO1xufVxuXG5VcmwucHJvdG90eXBlLnJlc29sdmVPYmplY3QgPSBmdW5jdGlvbihyZWxhdGl2ZSkge1xuICBpZiAodXRpbC5pc1N0cmluZyhyZWxhdGl2ZSkpIHtcbiAgICB2YXIgcmVsID0gbmV3IFVybCgpO1xuICAgIHJlbC5wYXJzZShyZWxhdGl2ZSwgZmFsc2UsIHRydWUpO1xuICAgIHJlbGF0aXZlID0gcmVsO1xuICB9XG5cbiAgdmFyIHJlc3VsdCA9IG5ldyBVcmwoKTtcbiAgdmFyIHRrZXlzID0gT2JqZWN0LmtleXModGhpcyk7XG4gIGZvciAodmFyIHRrID0gMDsgdGsgPCB0a2V5cy5sZW5ndGg7IHRrKyspIHtcbiAgICB2YXIgdGtleSA9IHRrZXlzW3RrXTtcbiAgICByZXN1bHRbdGtleV0gPSB0aGlzW3RrZXldO1xuICB9XG5cbiAgLy8gaGFzaCBpcyBhbHdheXMgb3ZlcnJpZGRlbiwgbm8gbWF0dGVyIHdoYXQuXG4gIC8vIGV2ZW4gaHJlZj1cIlwiIHdpbGwgcmVtb3ZlIGl0LlxuICByZXN1bHQuaGFzaCA9IHJlbGF0aXZlLmhhc2g7XG5cbiAgLy8gaWYgdGhlIHJlbGF0aXZlIHVybCBpcyBlbXB0eSwgdGhlbiB0aGVyZSdzIG5vdGhpbmcgbGVmdCB0byBkbyBoZXJlLlxuICBpZiAocmVsYXRpdmUuaHJlZiA9PT0gJycpIHtcbiAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLy8gaHJlZnMgbGlrZSAvL2Zvby9iYXIgYWx3YXlzIGN1dCB0byB0aGUgcHJvdG9jb2wuXG4gIGlmIChyZWxhdGl2ZS5zbGFzaGVzICYmICFyZWxhdGl2ZS5wcm90b2NvbCkge1xuICAgIC8vIHRha2UgZXZlcnl0aGluZyBleGNlcHQgdGhlIHByb3RvY29sIGZyb20gcmVsYXRpdmVcbiAgICB2YXIgcmtleXMgPSBPYmplY3Qua2V5cyhyZWxhdGl2ZSk7XG4gICAgZm9yICh2YXIgcmsgPSAwOyByayA8IHJrZXlzLmxlbmd0aDsgcmsrKykge1xuICAgICAgdmFyIHJrZXkgPSBya2V5c1tya107XG4gICAgICBpZiAocmtleSAhPT0gJ3Byb3RvY29sJylcbiAgICAgICAgcmVzdWx0W3JrZXldID0gcmVsYXRpdmVbcmtleV07XG4gICAgfVxuXG4gICAgLy91cmxQYXJzZSBhcHBlbmRzIHRyYWlsaW5nIC8gdG8gdXJscyBsaWtlIGh0dHA6Ly93d3cuZXhhbXBsZS5jb21cbiAgICBpZiAoc2xhc2hlZFByb3RvY29sW3Jlc3VsdC5wcm90b2NvbF0gJiZcbiAgICAgICAgcmVzdWx0Lmhvc3RuYW1lICYmICFyZXN1bHQucGF0aG5hbWUpIHtcbiAgICAgIHJlc3VsdC5wYXRoID0gcmVzdWx0LnBhdGhuYW1lID0gJy8nO1xuICAgIH1cblxuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBpZiAocmVsYXRpdmUucHJvdG9jb2wgJiYgcmVsYXRpdmUucHJvdG9jb2wgIT09IHJlc3VsdC5wcm90b2NvbCkge1xuICAgIC8vIGlmIGl0J3MgYSBrbm93biB1cmwgcHJvdG9jb2wsIHRoZW4gY2hhbmdpbmdcbiAgICAvLyB0aGUgcHJvdG9jb2wgZG9lcyB3ZWlyZCB0aGluZ3NcbiAgICAvLyBmaXJzdCwgaWYgaXQncyBub3QgZmlsZTosIHRoZW4gd2UgTVVTVCBoYXZlIGEgaG9zdCxcbiAgICAvLyBhbmQgaWYgdGhlcmUgd2FzIGEgcGF0aFxuICAgIC8vIHRvIGJlZ2luIHdpdGgsIHRoZW4gd2UgTVVTVCBoYXZlIGEgcGF0aC5cbiAgICAvLyBpZiBpdCBpcyBmaWxlOiwgdGhlbiB0aGUgaG9zdCBpcyBkcm9wcGVkLFxuICAgIC8vIGJlY2F1c2UgdGhhdCdzIGtub3duIHRvIGJlIGhvc3RsZXNzLlxuICAgIC8vIGFueXRoaW5nIGVsc2UgaXMgYXNzdW1lZCB0byBiZSBhYnNvbHV0ZS5cbiAgICBpZiAoIXNsYXNoZWRQcm90b2NvbFtyZWxhdGl2ZS5wcm90b2NvbF0pIHtcbiAgICAgIHZhciBrZXlzID0gT2JqZWN0LmtleXMocmVsYXRpdmUpO1xuICAgICAgZm9yICh2YXIgdiA9IDA7IHYgPCBrZXlzLmxlbmd0aDsgdisrKSB7XG4gICAgICAgIHZhciBrID0ga2V5c1t2XTtcbiAgICAgICAgcmVzdWx0W2tdID0gcmVsYXRpdmVba107XG4gICAgICB9XG4gICAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgcmVzdWx0LnByb3RvY29sID0gcmVsYXRpdmUucHJvdG9jb2w7XG4gICAgaWYgKCFyZWxhdGl2ZS5ob3N0ICYmICFob3N0bGVzc1Byb3RvY29sW3JlbGF0aXZlLnByb3RvY29sXSkge1xuICAgICAgdmFyIHJlbFBhdGggPSAocmVsYXRpdmUucGF0aG5hbWUgfHwgJycpLnNwbGl0KCcvJyk7XG4gICAgICB3aGlsZSAocmVsUGF0aC5sZW5ndGggJiYgIShyZWxhdGl2ZS5ob3N0ID0gcmVsUGF0aC5zaGlmdCgpKSk7XG4gICAgICBpZiAoIXJlbGF0aXZlLmhvc3QpIHJlbGF0aXZlLmhvc3QgPSAnJztcbiAgICAgIGlmICghcmVsYXRpdmUuaG9zdG5hbWUpIHJlbGF0aXZlLmhvc3RuYW1lID0gJyc7XG4gICAgICBpZiAocmVsUGF0aFswXSAhPT0gJycpIHJlbFBhdGgudW5zaGlmdCgnJyk7XG4gICAgICBpZiAocmVsUGF0aC5sZW5ndGggPCAyKSByZWxQYXRoLnVuc2hpZnQoJycpO1xuICAgICAgcmVzdWx0LnBhdGhuYW1lID0gcmVsUGF0aC5qb2luKCcvJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdC5wYXRobmFtZSA9IHJlbGF0aXZlLnBhdGhuYW1lO1xuICAgIH1cbiAgICByZXN1bHQuc2VhcmNoID0gcmVsYXRpdmUuc2VhcmNoO1xuICAgIHJlc3VsdC5xdWVyeSA9IHJlbGF0aXZlLnF1ZXJ5O1xuICAgIHJlc3VsdC5ob3N0ID0gcmVsYXRpdmUuaG9zdCB8fCAnJztcbiAgICByZXN1bHQuYXV0aCA9IHJlbGF0aXZlLmF1dGg7XG4gICAgcmVzdWx0Lmhvc3RuYW1lID0gcmVsYXRpdmUuaG9zdG5hbWUgfHwgcmVsYXRpdmUuaG9zdDtcbiAgICByZXN1bHQucG9ydCA9IHJlbGF0aXZlLnBvcnQ7XG4gICAgLy8gdG8gc3VwcG9ydCBodHRwLnJlcXVlc3RcbiAgICBpZiAocmVzdWx0LnBhdGhuYW1lIHx8IHJlc3VsdC5zZWFyY2gpIHtcbiAgICAgIHZhciBwID0gcmVzdWx0LnBhdGhuYW1lIHx8ICcnO1xuICAgICAgdmFyIHMgPSByZXN1bHQuc2VhcmNoIHx8ICcnO1xuICAgICAgcmVzdWx0LnBhdGggPSBwICsgcztcbiAgICB9XG4gICAgcmVzdWx0LnNsYXNoZXMgPSByZXN1bHQuc2xhc2hlcyB8fCByZWxhdGl2ZS5zbGFzaGVzO1xuICAgIHJlc3VsdC5ocmVmID0gcmVzdWx0LmZvcm1hdCgpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICB2YXIgaXNTb3VyY2VBYnMgPSAocmVzdWx0LnBhdGhuYW1lICYmIHJlc3VsdC5wYXRobmFtZS5jaGFyQXQoMCkgPT09ICcvJyksXG4gICAgICBpc1JlbEFicyA9IChcbiAgICAgICAgICByZWxhdGl2ZS5ob3N0IHx8XG4gICAgICAgICAgcmVsYXRpdmUucGF0aG5hbWUgJiYgcmVsYXRpdmUucGF0aG5hbWUuY2hhckF0KDApID09PSAnLydcbiAgICAgICksXG4gICAgICBtdXN0RW5kQWJzID0gKGlzUmVsQWJzIHx8IGlzU291cmNlQWJzIHx8XG4gICAgICAgICAgICAgICAgICAgIChyZXN1bHQuaG9zdCAmJiByZWxhdGl2ZS5wYXRobmFtZSkpLFxuICAgICAgcmVtb3ZlQWxsRG90cyA9IG11c3RFbmRBYnMsXG4gICAgICBzcmNQYXRoID0gcmVzdWx0LnBhdGhuYW1lICYmIHJlc3VsdC5wYXRobmFtZS5zcGxpdCgnLycpIHx8IFtdLFxuICAgICAgcmVsUGF0aCA9IHJlbGF0aXZlLnBhdGhuYW1lICYmIHJlbGF0aXZlLnBhdGhuYW1lLnNwbGl0KCcvJykgfHwgW10sXG4gICAgICBwc3ljaG90aWMgPSByZXN1bHQucHJvdG9jb2wgJiYgIXNsYXNoZWRQcm90b2NvbFtyZXN1bHQucHJvdG9jb2xdO1xuXG4gIC8vIGlmIHRoZSB1cmwgaXMgYSBub24tc2xhc2hlZCB1cmwsIHRoZW4gcmVsYXRpdmVcbiAgLy8gbGlua3MgbGlrZSAuLi8uLiBzaG91bGQgYmUgYWJsZVxuICAvLyB0byBjcmF3bCB1cCB0byB0aGUgaG9zdG5hbWUsIGFzIHdlbGwuICBUaGlzIGlzIHN0cmFuZ2UuXG4gIC8vIHJlc3VsdC5wcm90b2NvbCBoYXMgYWxyZWFkeSBiZWVuIHNldCBieSBub3cuXG4gIC8vIExhdGVyIG9uLCBwdXQgdGhlIGZpcnN0IHBhdGggcGFydCBpbnRvIHRoZSBob3N0IGZpZWxkLlxuICBpZiAocHN5Y2hvdGljKSB7XG4gICAgcmVzdWx0Lmhvc3RuYW1lID0gJyc7XG4gICAgcmVzdWx0LnBvcnQgPSBudWxsO1xuICAgIGlmIChyZXN1bHQuaG9zdCkge1xuICAgICAgaWYgKHNyY1BhdGhbMF0gPT09ICcnKSBzcmNQYXRoWzBdID0gcmVzdWx0Lmhvc3Q7XG4gICAgICBlbHNlIHNyY1BhdGgudW5zaGlmdChyZXN1bHQuaG9zdCk7XG4gICAgfVxuICAgIHJlc3VsdC5ob3N0ID0gJyc7XG4gICAgaWYgKHJlbGF0aXZlLnByb3RvY29sKSB7XG4gICAgICByZWxhdGl2ZS5ob3N0bmFtZSA9IG51bGw7XG4gICAgICByZWxhdGl2ZS5wb3J0ID0gbnVsbDtcbiAgICAgIGlmIChyZWxhdGl2ZS5ob3N0KSB7XG4gICAgICAgIGlmIChyZWxQYXRoWzBdID09PSAnJykgcmVsUGF0aFswXSA9IHJlbGF0aXZlLmhvc3Q7XG4gICAgICAgIGVsc2UgcmVsUGF0aC51bnNoaWZ0KHJlbGF0aXZlLmhvc3QpO1xuICAgICAgfVxuICAgICAgcmVsYXRpdmUuaG9zdCA9IG51bGw7XG4gICAgfVxuICAgIG11c3RFbmRBYnMgPSBtdXN0RW5kQWJzICYmIChyZWxQYXRoWzBdID09PSAnJyB8fCBzcmNQYXRoWzBdID09PSAnJyk7XG4gIH1cblxuICBpZiAoaXNSZWxBYnMpIHtcbiAgICAvLyBpdCdzIGFic29sdXRlLlxuICAgIHJlc3VsdC5ob3N0ID0gKHJlbGF0aXZlLmhvc3QgfHwgcmVsYXRpdmUuaG9zdCA9PT0gJycpID9cbiAgICAgICAgICAgICAgICAgIHJlbGF0aXZlLmhvc3QgOiByZXN1bHQuaG9zdDtcbiAgICByZXN1bHQuaG9zdG5hbWUgPSAocmVsYXRpdmUuaG9zdG5hbWUgfHwgcmVsYXRpdmUuaG9zdG5hbWUgPT09ICcnKSA/XG4gICAgICAgICAgICAgICAgICAgICAgcmVsYXRpdmUuaG9zdG5hbWUgOiByZXN1bHQuaG9zdG5hbWU7XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgICBzcmNQYXRoID0gcmVsUGF0aDtcbiAgICAvLyBmYWxsIHRocm91Z2ggdG8gdGhlIGRvdC1oYW5kbGluZyBiZWxvdy5cbiAgfSBlbHNlIGlmIChyZWxQYXRoLmxlbmd0aCkge1xuICAgIC8vIGl0J3MgcmVsYXRpdmVcbiAgICAvLyB0aHJvdyBhd2F5IHRoZSBleGlzdGluZyBmaWxlLCBhbmQgdGFrZSB0aGUgbmV3IHBhdGggaW5zdGVhZC5cbiAgICBpZiAoIXNyY1BhdGgpIHNyY1BhdGggPSBbXTtcbiAgICBzcmNQYXRoLnBvcCgpO1xuICAgIHNyY1BhdGggPSBzcmNQYXRoLmNvbmNhdChyZWxQYXRoKTtcbiAgICByZXN1bHQuc2VhcmNoID0gcmVsYXRpdmUuc2VhcmNoO1xuICAgIHJlc3VsdC5xdWVyeSA9IHJlbGF0aXZlLnF1ZXJ5O1xuICB9IGVsc2UgaWYgKCF1dGlsLmlzTnVsbE9yVW5kZWZpbmVkKHJlbGF0aXZlLnNlYXJjaCkpIHtcbiAgICAvLyBqdXN0IHB1bGwgb3V0IHRoZSBzZWFyY2guXG4gICAgLy8gbGlrZSBocmVmPSc/Zm9vJy5cbiAgICAvLyBQdXQgdGhpcyBhZnRlciB0aGUgb3RoZXIgdHdvIGNhc2VzIGJlY2F1c2UgaXQgc2ltcGxpZmllcyB0aGUgYm9vbGVhbnNcbiAgICBpZiAocHN5Y2hvdGljKSB7XG4gICAgICByZXN1bHQuaG9zdG5hbWUgPSByZXN1bHQuaG9zdCA9IHNyY1BhdGguc2hpZnQoKTtcbiAgICAgIC8vb2NjYXRpb25hbHkgdGhlIGF1dGggY2FuIGdldCBzdHVjayBvbmx5IGluIGhvc3RcbiAgICAgIC8vdGhpcyBlc3BlY2lhbGx5IGhhcHBlbnMgaW4gY2FzZXMgbGlrZVxuICAgICAgLy91cmwucmVzb2x2ZU9iamVjdCgnbWFpbHRvOmxvY2FsMUBkb21haW4xJywgJ2xvY2FsMkBkb21haW4yJylcbiAgICAgIHZhciBhdXRoSW5Ib3N0ID0gcmVzdWx0Lmhvc3QgJiYgcmVzdWx0Lmhvc3QuaW5kZXhPZignQCcpID4gMCA/XG4gICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5ob3N0LnNwbGl0KCdAJykgOiBmYWxzZTtcbiAgICAgIGlmIChhdXRoSW5Ib3N0KSB7XG4gICAgICAgIHJlc3VsdC5hdXRoID0gYXV0aEluSG9zdC5zaGlmdCgpO1xuICAgICAgICByZXN1bHQuaG9zdCA9IHJlc3VsdC5ob3N0bmFtZSA9IGF1dGhJbkhvc3Quc2hpZnQoKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0LnNlYXJjaCA9IHJlbGF0aXZlLnNlYXJjaDtcbiAgICByZXN1bHQucXVlcnkgPSByZWxhdGl2ZS5xdWVyeTtcbiAgICAvL3RvIHN1cHBvcnQgaHR0cC5yZXF1ZXN0XG4gICAgaWYgKCF1dGlsLmlzTnVsbChyZXN1bHQucGF0aG5hbWUpIHx8ICF1dGlsLmlzTnVsbChyZXN1bHQuc2VhcmNoKSkge1xuICAgICAgcmVzdWx0LnBhdGggPSAocmVzdWx0LnBhdGhuYW1lID8gcmVzdWx0LnBhdGhuYW1lIDogJycpICtcbiAgICAgICAgICAgICAgICAgICAgKHJlc3VsdC5zZWFyY2ggPyByZXN1bHQuc2VhcmNoIDogJycpO1xuICAgIH1cbiAgICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgaWYgKCFzcmNQYXRoLmxlbmd0aCkge1xuICAgIC8vIG5vIHBhdGggYXQgYWxsLiAgZWFzeS5cbiAgICAvLyB3ZSd2ZSBhbHJlYWR5IGhhbmRsZWQgdGhlIG90aGVyIHN0dWZmIGFib3ZlLlxuICAgIHJlc3VsdC5wYXRobmFtZSA9IG51bGw7XG4gICAgLy90byBzdXBwb3J0IGh0dHAucmVxdWVzdFxuICAgIGlmIChyZXN1bHQuc2VhcmNoKSB7XG4gICAgICByZXN1bHQucGF0aCA9ICcvJyArIHJlc3VsdC5zZWFyY2g7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdC5wYXRoID0gbnVsbDtcbiAgICB9XG4gICAgcmVzdWx0LmhyZWYgPSByZXN1bHQuZm9ybWF0KCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIC8vIGlmIGEgdXJsIEVORHMgaW4gLiBvciAuLiwgdGhlbiBpdCBtdXN0IGdldCBhIHRyYWlsaW5nIHNsYXNoLlxuICAvLyBob3dldmVyLCBpZiBpdCBlbmRzIGluIGFueXRoaW5nIGVsc2Ugbm9uLXNsYXNoeSxcbiAgLy8gdGhlbiBpdCBtdXN0IE5PVCBnZXQgYSB0cmFpbGluZyBzbGFzaC5cbiAgdmFyIGxhc3QgPSBzcmNQYXRoLnNsaWNlKC0xKVswXTtcbiAgdmFyIGhhc1RyYWlsaW5nU2xhc2ggPSAoXG4gICAgICAocmVzdWx0Lmhvc3QgfHwgcmVsYXRpdmUuaG9zdCB8fCBzcmNQYXRoLmxlbmd0aCA+IDEpICYmXG4gICAgICAobGFzdCA9PT0gJy4nIHx8IGxhc3QgPT09ICcuLicpIHx8IGxhc3QgPT09ICcnKTtcblxuICAvLyBzdHJpcCBzaW5nbGUgZG90cywgcmVzb2x2ZSBkb3VibGUgZG90cyB0byBwYXJlbnQgZGlyXG4gIC8vIGlmIHRoZSBwYXRoIHRyaWVzIHRvIGdvIGFib3ZlIHRoZSByb290LCBgdXBgIGVuZHMgdXAgPiAwXG4gIHZhciB1cCA9IDA7XG4gIGZvciAodmFyIGkgPSBzcmNQYXRoLmxlbmd0aDsgaSA+PSAwOyBpLS0pIHtcbiAgICBsYXN0ID0gc3JjUGF0aFtpXTtcbiAgICBpZiAobGFzdCA9PT0gJy4nKSB7XG4gICAgICBzcmNQYXRoLnNwbGljZShpLCAxKTtcbiAgICB9IGVsc2UgaWYgKGxhc3QgPT09ICcuLicpIHtcbiAgICAgIHNyY1BhdGguc3BsaWNlKGksIDEpO1xuICAgICAgdXArKztcbiAgICB9IGVsc2UgaWYgKHVwKSB7XG4gICAgICBzcmNQYXRoLnNwbGljZShpLCAxKTtcbiAgICAgIHVwLS07XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlIHBhdGggaXMgYWxsb3dlZCB0byBnbyBhYm92ZSB0aGUgcm9vdCwgcmVzdG9yZSBsZWFkaW5nIC4uc1xuICBpZiAoIW11c3RFbmRBYnMgJiYgIXJlbW92ZUFsbERvdHMpIHtcbiAgICBmb3IgKDsgdXAtLTsgdXApIHtcbiAgICAgIHNyY1BhdGgudW5zaGlmdCgnLi4nKTtcbiAgICB9XG4gIH1cblxuICBpZiAobXVzdEVuZEFicyAmJiBzcmNQYXRoWzBdICE9PSAnJyAmJlxuICAgICAgKCFzcmNQYXRoWzBdIHx8IHNyY1BhdGhbMF0uY2hhckF0KDApICE9PSAnLycpKSB7XG4gICAgc3JjUGF0aC51bnNoaWZ0KCcnKTtcbiAgfVxuXG4gIGlmIChoYXNUcmFpbGluZ1NsYXNoICYmIChzcmNQYXRoLmpvaW4oJy8nKS5zdWJzdHIoLTEpICE9PSAnLycpKSB7XG4gICAgc3JjUGF0aC5wdXNoKCcnKTtcbiAgfVxuXG4gIHZhciBpc0Fic29sdXRlID0gc3JjUGF0aFswXSA9PT0gJycgfHxcbiAgICAgIChzcmNQYXRoWzBdICYmIHNyY1BhdGhbMF0uY2hhckF0KDApID09PSAnLycpO1xuXG4gIC8vIHB1dCB0aGUgaG9zdCBiYWNrXG4gIGlmIChwc3ljaG90aWMpIHtcbiAgICByZXN1bHQuaG9zdG5hbWUgPSByZXN1bHQuaG9zdCA9IGlzQWJzb2x1dGUgPyAnJyA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcmNQYXRoLmxlbmd0aCA/IHNyY1BhdGguc2hpZnQoKSA6ICcnO1xuICAgIC8vb2NjYXRpb25hbHkgdGhlIGF1dGggY2FuIGdldCBzdHVjayBvbmx5IGluIGhvc3RcbiAgICAvL3RoaXMgZXNwZWNpYWxseSBoYXBwZW5zIGluIGNhc2VzIGxpa2VcbiAgICAvL3VybC5yZXNvbHZlT2JqZWN0KCdtYWlsdG86bG9jYWwxQGRvbWFpbjEnLCAnbG9jYWwyQGRvbWFpbjInKVxuICAgIHZhciBhdXRoSW5Ib3N0ID0gcmVzdWx0Lmhvc3QgJiYgcmVzdWx0Lmhvc3QuaW5kZXhPZignQCcpID4gMCA/XG4gICAgICAgICAgICAgICAgICAgICByZXN1bHQuaG9zdC5zcGxpdCgnQCcpIDogZmFsc2U7XG4gICAgaWYgKGF1dGhJbkhvc3QpIHtcbiAgICAgIHJlc3VsdC5hdXRoID0gYXV0aEluSG9zdC5zaGlmdCgpO1xuICAgICAgcmVzdWx0Lmhvc3QgPSByZXN1bHQuaG9zdG5hbWUgPSBhdXRoSW5Ib3N0LnNoaWZ0KCk7XG4gICAgfVxuICB9XG5cbiAgbXVzdEVuZEFicyA9IG11c3RFbmRBYnMgfHwgKHJlc3VsdC5ob3N0ICYmIHNyY1BhdGgubGVuZ3RoKTtcblxuICBpZiAobXVzdEVuZEFicyAmJiAhaXNBYnNvbHV0ZSkge1xuICAgIHNyY1BhdGgudW5zaGlmdCgnJyk7XG4gIH1cblxuICBpZiAoIXNyY1BhdGgubGVuZ3RoKSB7XG4gICAgcmVzdWx0LnBhdGhuYW1lID0gbnVsbDtcbiAgICByZXN1bHQucGF0aCA9IG51bGw7XG4gIH0gZWxzZSB7XG4gICAgcmVzdWx0LnBhdGhuYW1lID0gc3JjUGF0aC5qb2luKCcvJyk7XG4gIH1cblxuICAvL3RvIHN1cHBvcnQgcmVxdWVzdC5odHRwXG4gIGlmICghdXRpbC5pc051bGwocmVzdWx0LnBhdGhuYW1lKSB8fCAhdXRpbC5pc051bGwocmVzdWx0LnNlYXJjaCkpIHtcbiAgICByZXN1bHQucGF0aCA9IChyZXN1bHQucGF0aG5hbWUgPyByZXN1bHQucGF0aG5hbWUgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgKHJlc3VsdC5zZWFyY2ggPyByZXN1bHQuc2VhcmNoIDogJycpO1xuICB9XG4gIHJlc3VsdC5hdXRoID0gcmVsYXRpdmUuYXV0aCB8fCByZXN1bHQuYXV0aDtcbiAgcmVzdWx0LnNsYXNoZXMgPSByZXN1bHQuc2xhc2hlcyB8fCByZWxhdGl2ZS5zbGFzaGVzO1xuICByZXN1bHQuaHJlZiA9IHJlc3VsdC5mb3JtYXQoKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cblVybC5wcm90b3R5cGUucGFyc2VIb3N0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciBob3N0ID0gdGhpcy5ob3N0O1xuICB2YXIgcG9ydCA9IHBvcnRQYXR0ZXJuLmV4ZWMoaG9zdCk7XG4gIGlmIChwb3J0KSB7XG4gICAgcG9ydCA9IHBvcnRbMF07XG4gICAgaWYgKHBvcnQgIT09ICc6Jykge1xuICAgICAgdGhpcy5wb3J0ID0gcG9ydC5zdWJzdHIoMSk7XG4gICAgfVxuICAgIGhvc3QgPSBob3N0LnN1YnN0cigwLCBob3N0Lmxlbmd0aCAtIHBvcnQubGVuZ3RoKTtcbiAgfVxuICBpZiAoaG9zdCkgdGhpcy5ob3N0bmFtZSA9IGhvc3Q7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgaXNTdHJpbmc6IGZ1bmN0aW9uKGFyZykge1xuICAgIHJldHVybiB0eXBlb2YoYXJnKSA9PT0gJ3N0cmluZyc7XG4gIH0sXG4gIGlzT2JqZWN0OiBmdW5jdGlvbihhcmcpIHtcbiAgICByZXR1cm4gdHlwZW9mKGFyZykgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbiAgfSxcbiAgaXNOdWxsOiBmdW5jdGlvbihhcmcpIHtcbiAgICByZXR1cm4gYXJnID09PSBudWxsO1xuICB9LFxuICBpc051bGxPclVuZGVmaW5lZDogZnVuY3Rpb24oYXJnKSB7XG4gICAgcmV0dXJuIGFyZyA9PSBudWxsO1xuICB9XG59O1xuIiwiXG4vKipcbiAqIE1vZHVsZSBleHBvcnRzLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZGVwcmVjYXRlO1xuXG4vKipcbiAqIE1hcmsgdGhhdCBhIG1ldGhvZCBzaG91bGQgbm90IGJlIHVzZWQuXG4gKiBSZXR1cm5zIGEgbW9kaWZpZWQgZnVuY3Rpb24gd2hpY2ggd2FybnMgb25jZSBieSBkZWZhdWx0LlxuICpcbiAqIElmIGBsb2NhbFN0b3JhZ2Uubm9EZXByZWNhdGlvbiA9IHRydWVgIGlzIHNldCwgdGhlbiBpdCBpcyBhIG5vLW9wLlxuICpcbiAqIElmIGBsb2NhbFN0b3JhZ2UudGhyb3dEZXByZWNhdGlvbiA9IHRydWVgIGlzIHNldCwgdGhlbiBkZXByZWNhdGVkIGZ1bmN0aW9uc1xuICogd2lsbCB0aHJvdyBhbiBFcnJvciB3aGVuIGludm9rZWQuXG4gKlxuICogSWYgYGxvY2FsU3RvcmFnZS50cmFjZURlcHJlY2F0aW9uID0gdHJ1ZWAgaXMgc2V0LCB0aGVuIGRlcHJlY2F0ZWQgZnVuY3Rpb25zXG4gKiB3aWxsIGludm9rZSBgY29uc29sZS50cmFjZSgpYCBpbnN0ZWFkIG9mIGBjb25zb2xlLmVycm9yKClgLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gdGhlIGZ1bmN0aW9uIHRvIGRlcHJlY2F0ZVxuICogQHBhcmFtIHtTdHJpbmd9IG1zZyAtIHRoZSBzdHJpbmcgdG8gcHJpbnQgdG8gdGhlIGNvbnNvbGUgd2hlbiBgZm5gIGlzIGludm9rZWRcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gYSBuZXcgXCJkZXByZWNhdGVkXCIgdmVyc2lvbiBvZiBgZm5gXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGRlcHJlY2F0ZSAoZm4sIG1zZykge1xuICBpZiAoY29uZmlnKCdub0RlcHJlY2F0aW9uJykpIHtcbiAgICByZXR1cm4gZm47XG4gIH1cblxuICB2YXIgd2FybmVkID0gZmFsc2U7XG4gIGZ1bmN0aW9uIGRlcHJlY2F0ZWQoKSB7XG4gICAgaWYgKCF3YXJuZWQpIHtcbiAgICAgIGlmIChjb25maWcoJ3Rocm93RGVwcmVjYXRpb24nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgIH0gZWxzZSBpZiAoY29uZmlnKCd0cmFjZURlcHJlY2F0aW9uJykpIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS53YXJuKG1zZyk7XG4gICAgICB9XG4gICAgICB3YXJuZWQgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHJldHVybiBkZXByZWNhdGVkO1xufVxuXG4vKipcbiAqIENoZWNrcyBgbG9jYWxTdG9yYWdlYCBmb3IgYm9vbGVhbiB2YWx1ZXMgZm9yIHRoZSBnaXZlbiBgbmFtZWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqIEByZXR1cm5zIHtCb29sZWFufVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gY29uZmlnIChuYW1lKSB7XG4gIC8vIGFjY2Vzc2luZyBnbG9iYWwubG9jYWxTdG9yYWdlIGNhbiB0cmlnZ2VyIGEgRE9NRXhjZXB0aW9uIGluIHNhbmRib3hlZCBpZnJhbWVzXG4gIHRyeSB7XG4gICAgaWYgKCFnbG9iYWwubG9jYWxTdG9yYWdlKSByZXR1cm4gZmFsc2U7XG4gIH0gY2F0Y2ggKF8pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgdmFyIHZhbCA9IGdsb2JhbC5sb2NhbFN0b3JhZ2VbbmFtZV07XG4gIGlmIChudWxsID09IHZhbCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gU3RyaW5nKHZhbCkudG9Mb3dlckNhc2UoKSA9PT0gJ3RydWUnO1xufVxuIiwiLyoqXG4gKiBXcmFwcGVyIGZvciBidWlsdC1pbiBodHRwLmpzIHRvIGVtdWxhdGUgdGhlIGJyb3dzZXIgWE1MSHR0cFJlcXVlc3Qgb2JqZWN0LlxuICpcbiAqIFRoaXMgY2FuIGJlIHVzZWQgd2l0aCBKUyBkZXNpZ25lZCBmb3IgYnJvd3NlcnMgdG8gaW1wcm92ZSByZXVzZSBvZiBjb2RlIGFuZFxuICogYWxsb3cgdGhlIHVzZSBvZiBleGlzdGluZyBsaWJyYXJpZXMuXG4gKlxuICogVXNhZ2U6IGluY2x1ZGUoXCJYTUxIdHRwUmVxdWVzdC5qc1wiKSBhbmQgdXNlIFhNTEh0dHBSZXF1ZXN0IHBlciBXM0Mgc3BlY3MuXG4gKlxuICogQGF1dGhvciBEYW4gRGVGZWxpcHBpIDxkYW5AZHJpdmVyZGFuLmNvbT5cbiAqIEBjb250cmlidXRvciBEYXZpZCBFbGxpcyA8ZC5mLmVsbGlzQGllZWUub3JnPlxuICogQGxpY2Vuc2UgTUlUXG4gKi9cblxudmFyIFVybCA9IHJlcXVpcmUoXCJ1cmxcIik7XG52YXIgc3Bhd24gPSByZXF1aXJlKFwiY2hpbGRfcHJvY2Vzc1wiKS5zcGF3bjtcbnZhciBmcyA9IHJlcXVpcmUoXCJmc1wiKTtcblxuZXhwb3J0cy5YTUxIdHRwUmVxdWVzdCA9IGZ1bmN0aW9uKCkge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICAvKipcbiAgICogUHJpdmF0ZSB2YXJpYWJsZXNcbiAgICovXG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIGh0dHAgPSByZXF1aXJlKFwiaHR0cFwiKTtcbiAgdmFyIGh0dHBzID0gcmVxdWlyZShcImh0dHBzXCIpO1xuXG4gIC8vIEhvbGRzIGh0dHAuanMgb2JqZWN0c1xuICB2YXIgcmVxdWVzdDtcbiAgdmFyIHJlc3BvbnNlO1xuXG4gIC8vIFJlcXVlc3Qgc2V0dGluZ3NcbiAgdmFyIHNldHRpbmdzID0ge307XG5cbiAgLy8gRGlzYWJsZSBoZWFkZXIgYmxhY2tsaXN0LlxuICAvLyBOb3QgcGFydCBvZiBYSFIgc3BlY3MuXG4gIHZhciBkaXNhYmxlSGVhZGVyQ2hlY2sgPSBmYWxzZTtcblxuICAvLyBTZXQgc29tZSBkZWZhdWx0IGhlYWRlcnNcbiAgdmFyIGRlZmF1bHRIZWFkZXJzID0ge1xuICAgIFwiVXNlci1BZ2VudFwiOiBcIm5vZGUtWE1MSHR0cFJlcXVlc3RcIixcbiAgICBcIkFjY2VwdFwiOiBcIiovKlwiLFxuICB9O1xuXG4gIHZhciBoZWFkZXJzID0ge307XG4gIHZhciBoZWFkZXJzQ2FzZSA9IHt9O1xuXG4gIC8vIFRoZXNlIGhlYWRlcnMgYXJlIG5vdCB1c2VyIHNldGFibGUuXG4gIC8vIFRoZSBmb2xsb3dpbmcgYXJlIGFsbG93ZWQgYnV0IGJhbm5lZCBpbiB0aGUgc3BlYzpcbiAgLy8gKiB1c2VyLWFnZW50XG4gIHZhciBmb3JiaWRkZW5SZXF1ZXN0SGVhZGVycyA9IFtcbiAgICBcImFjY2VwdC1jaGFyc2V0XCIsXG4gICAgXCJhY2NlcHQtZW5jb2RpbmdcIixcbiAgICBcImFjY2Vzcy1jb250cm9sLXJlcXVlc3QtaGVhZGVyc1wiLFxuICAgIFwiYWNjZXNzLWNvbnRyb2wtcmVxdWVzdC1tZXRob2RcIixcbiAgICBcImNvbm5lY3Rpb25cIixcbiAgICBcImNvbnRlbnQtbGVuZ3RoXCIsXG4gICAgXCJjb250ZW50LXRyYW5zZmVyLWVuY29kaW5nXCIsXG4gICAgXCJjb29raWVcIixcbiAgICBcImNvb2tpZTJcIixcbiAgICBcImRhdGVcIixcbiAgICBcImV4cGVjdFwiLFxuICAgIFwiaG9zdFwiLFxuICAgIFwia2VlcC1hbGl2ZVwiLFxuICAgIFwib3JpZ2luXCIsXG4gICAgXCJyZWZlcmVyXCIsXG4gICAgXCJ0ZVwiLFxuICAgIFwidHJhaWxlclwiLFxuICAgIFwidHJhbnNmZXItZW5jb2RpbmdcIixcbiAgICBcInVwZ3JhZGVcIixcbiAgICBcInZpYVwiXG4gIF07XG5cbiAgLy8gVGhlc2UgcmVxdWVzdCBtZXRob2RzIGFyZSBub3QgYWxsb3dlZFxuICB2YXIgZm9yYmlkZGVuUmVxdWVzdE1ldGhvZHMgPSBbXG4gICAgXCJUUkFDRVwiLFxuICAgIFwiVFJBQ0tcIixcbiAgICBcIkNPTk5FQ1RcIlxuICBdO1xuXG4gIC8vIFNlbmQgZmxhZ1xuICB2YXIgc2VuZEZsYWcgPSBmYWxzZTtcbiAgLy8gRXJyb3IgZmxhZywgdXNlZCB3aGVuIGVycm9ycyBvY2N1ciBvciBhYm9ydCBpcyBjYWxsZWRcbiAgdmFyIGVycm9yRmxhZyA9IGZhbHNlO1xuXG4gIC8vIEV2ZW50IGxpc3RlbmVyc1xuICB2YXIgbGlzdGVuZXJzID0ge307XG5cbiAgLyoqXG4gICAqIENvbnN0YW50c1xuICAgKi9cblxuICB0aGlzLlVOU0VOVCA9IDA7XG4gIHRoaXMuT1BFTkVEID0gMTtcbiAgdGhpcy5IRUFERVJTX1JFQ0VJVkVEID0gMjtcbiAgdGhpcy5MT0FESU5HID0gMztcbiAgdGhpcy5ET05FID0gNDtcblxuICAvKipcbiAgICogUHVibGljIHZhcnNcbiAgICovXG5cbiAgLy8gQ3VycmVudCBzdGF0ZVxuICB0aGlzLnJlYWR5U3RhdGUgPSB0aGlzLlVOU0VOVDtcblxuICAvLyBkZWZhdWx0IHJlYWR5IHN0YXRlIGNoYW5nZSBoYW5kbGVyIGluIGNhc2Ugb25lIGlzIG5vdCBzZXQgb3IgaXMgc2V0IGxhdGVcbiAgdGhpcy5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBudWxsO1xuXG4gIC8vIFJlc3VsdCAmIHJlc3BvbnNlXG4gIHRoaXMucmVzcG9uc2VUZXh0ID0gXCJcIjtcbiAgdGhpcy5yZXNwb25zZVhNTCA9IFwiXCI7XG4gIHRoaXMuc3RhdHVzID0gbnVsbDtcbiAgdGhpcy5zdGF0dXNUZXh0ID0gbnVsbDtcbiAgXG4gIC8vIFdoZXRoZXIgY3Jvc3Mtc2l0ZSBBY2Nlc3MtQ29udHJvbCByZXF1ZXN0cyBzaG91bGQgYmUgbWFkZSB1c2luZ1xuICAvLyBjcmVkZW50aWFscyBzdWNoIGFzIGNvb2tpZXMgb3IgYXV0aG9yaXphdGlvbiBoZWFkZXJzXG4gIHRoaXMud2l0aENyZWRlbnRpYWxzID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIFByaXZhdGUgbWV0aG9kc1xuICAgKi9cblxuICAvKipcbiAgICogQ2hlY2sgaWYgdGhlIHNwZWNpZmllZCBoZWFkZXIgaXMgYWxsb3dlZC5cbiAgICpcbiAgICogQHBhcmFtIHN0cmluZyBoZWFkZXIgSGVhZGVyIHRvIHZhbGlkYXRlXG4gICAqIEByZXR1cm4gYm9vbGVhbiBGYWxzZSBpZiBub3QgYWxsb3dlZCwgb3RoZXJ3aXNlIHRydWVcbiAgICovXG4gIHZhciBpc0FsbG93ZWRIdHRwSGVhZGVyID0gZnVuY3Rpb24oaGVhZGVyKSB7XG4gICAgcmV0dXJuIGRpc2FibGVIZWFkZXJDaGVjayB8fCAoaGVhZGVyICYmIGZvcmJpZGRlblJlcXVlc3RIZWFkZXJzLmluZGV4T2YoaGVhZGVyLnRvTG93ZXJDYXNlKCkpID09PSAtMSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBzcGVjaWZpZWQgbWV0aG9kIGlzIGFsbG93ZWQuXG4gICAqXG4gICAqIEBwYXJhbSBzdHJpbmcgbWV0aG9kIFJlcXVlc3QgbWV0aG9kIHRvIHZhbGlkYXRlXG4gICAqIEByZXR1cm4gYm9vbGVhbiBGYWxzZSBpZiBub3QgYWxsb3dlZCwgb3RoZXJ3aXNlIHRydWVcbiAgICovXG4gIHZhciBpc0FsbG93ZWRIdHRwTWV0aG9kID0gZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgcmV0dXJuIChtZXRob2QgJiYgZm9yYmlkZGVuUmVxdWVzdE1ldGhvZHMuaW5kZXhPZihtZXRob2QpID09PSAtMSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFB1YmxpYyBtZXRob2RzXG4gICAqL1xuXG4gIC8qKlxuICAgKiBPcGVuIHRoZSBjb25uZWN0aW9uLiBDdXJyZW50bHkgc3VwcG9ydHMgbG9jYWwgc2VydmVyIHJlcXVlc3RzLlxuICAgKlxuICAgKiBAcGFyYW0gc3RyaW5nIG1ldGhvZCBDb25uZWN0aW9uIG1ldGhvZCAoZWcgR0VULCBQT1NUKVxuICAgKiBAcGFyYW0gc3RyaW5nIHVybCBVUkwgZm9yIHRoZSBjb25uZWN0aW9uLlxuICAgKiBAcGFyYW0gYm9vbGVhbiBhc3luYyBBc3luY2hyb25vdXMgY29ubmVjdGlvbi4gRGVmYXVsdCBpcyB0cnVlLlxuICAgKiBAcGFyYW0gc3RyaW5nIHVzZXIgVXNlcm5hbWUgZm9yIGJhc2ljIGF1dGhlbnRpY2F0aW9uIChvcHRpb25hbClcbiAgICogQHBhcmFtIHN0cmluZyBwYXNzd29yZCBQYXNzd29yZCBmb3IgYmFzaWMgYXV0aGVudGljYXRpb24gKG9wdGlvbmFsKVxuICAgKi9cbiAgdGhpcy5vcGVuID0gZnVuY3Rpb24obWV0aG9kLCB1cmwsIGFzeW5jLCB1c2VyLCBwYXNzd29yZCkge1xuICAgIHRoaXMuYWJvcnQoKTtcbiAgICBlcnJvckZsYWcgPSBmYWxzZTtcblxuICAgIC8vIENoZWNrIGZvciB2YWxpZCByZXF1ZXN0IG1ldGhvZFxuICAgIGlmICghaXNBbGxvd2VkSHR0cE1ldGhvZChtZXRob2QpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJTZWN1cml0eUVycm9yOiBSZXF1ZXN0IG1ldGhvZCBub3QgYWxsb3dlZFwiKTtcbiAgICB9XG5cbiAgICBzZXR0aW5ncyA9IHtcbiAgICAgIFwibWV0aG9kXCI6IG1ldGhvZCxcbiAgICAgIFwidXJsXCI6IHVybC50b1N0cmluZygpLFxuICAgICAgXCJhc3luY1wiOiAodHlwZW9mIGFzeW5jICE9PSBcImJvb2xlYW5cIiA/IHRydWUgOiBhc3luYyksXG4gICAgICBcInVzZXJcIjogdXNlciB8fCBudWxsLFxuICAgICAgXCJwYXNzd29yZFwiOiBwYXNzd29yZCB8fCBudWxsXG4gICAgfTtcblxuICAgIHNldFN0YXRlKHRoaXMuT1BFTkVEKTtcbiAgfTtcblxuICAvKipcbiAgICogRGlzYWJsZXMgb3IgZW5hYmxlcyBpc0FsbG93ZWRIdHRwSGVhZGVyKCkgY2hlY2sgdGhlIHJlcXVlc3QuIEVuYWJsZWQgYnkgZGVmYXVsdC5cbiAgICogVGhpcyBkb2VzIG5vdCBjb25mb3JtIHRvIHRoZSBXM0Mgc3BlYy5cbiAgICpcbiAgICogQHBhcmFtIGJvb2xlYW4gc3RhdGUgRW5hYmxlIG9yIGRpc2FibGUgaGVhZGVyIGNoZWNraW5nLlxuICAgKi9cbiAgdGhpcy5zZXREaXNhYmxlSGVhZGVyQ2hlY2sgPSBmdW5jdGlvbihzdGF0ZSkge1xuICAgIGRpc2FibGVIZWFkZXJDaGVjayA9IHN0YXRlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBTZXRzIGEgaGVhZGVyIGZvciB0aGUgcmVxdWVzdCBvciBhcHBlbmRzIHRoZSB2YWx1ZSBpZiBvbmUgaXMgYWxyZWFkeSBzZXQuXG4gICAqXG4gICAqIEBwYXJhbSBzdHJpbmcgaGVhZGVyIEhlYWRlciBuYW1lXG4gICAqIEBwYXJhbSBzdHJpbmcgdmFsdWUgSGVhZGVyIHZhbHVlXG4gICAqL1xuICB0aGlzLnNldFJlcXVlc3RIZWFkZXIgPSBmdW5jdGlvbihoZWFkZXIsIHZhbHVlKSB7XG4gICAgaWYgKHRoaXMucmVhZHlTdGF0ZSAhPT0gdGhpcy5PUEVORUQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIklOVkFMSURfU1RBVEVfRVJSOiBzZXRSZXF1ZXN0SGVhZGVyIGNhbiBvbmx5IGJlIGNhbGxlZCB3aGVuIHN0YXRlIGlzIE9QRU5cIik7XG4gICAgfVxuICAgIGlmICghaXNBbGxvd2VkSHR0cEhlYWRlcihoZWFkZXIpKSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJSZWZ1c2VkIHRvIHNldCB1bnNhZmUgaGVhZGVyIFxcXCJcIiArIGhlYWRlciArIFwiXFxcIlwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHNlbmRGbGFnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJTlZBTElEX1NUQVRFX0VSUjogc2VuZCBmbGFnIGlzIHRydWVcIik7XG4gICAgfVxuICAgIGhlYWRlciA9IGhlYWRlcnNDYXNlW2hlYWRlci50b0xvd2VyQ2FzZSgpXSB8fCBoZWFkZXI7XG4gICAgaGVhZGVyc0Nhc2VbaGVhZGVyLnRvTG93ZXJDYXNlKCldID0gaGVhZGVyO1xuICAgIGhlYWRlcnNbaGVhZGVyXSA9IGhlYWRlcnNbaGVhZGVyXSA/IGhlYWRlcnNbaGVhZGVyXSArICcsICcgKyB2YWx1ZSA6IHZhbHVlO1xuICB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIGEgaGVhZGVyIGZyb20gdGhlIHNlcnZlciByZXNwb25zZS5cbiAgICpcbiAgICogQHBhcmFtIHN0cmluZyBoZWFkZXIgTmFtZSBvZiBoZWFkZXIgdG8gZ2V0LlxuICAgKiBAcmV0dXJuIHN0cmluZyBUZXh0IG9mIHRoZSBoZWFkZXIgb3IgbnVsbCBpZiBpdCBkb2Vzbid0IGV4aXN0LlxuICAgKi9cbiAgdGhpcy5nZXRSZXNwb25zZUhlYWRlciA9IGZ1bmN0aW9uKGhlYWRlcikge1xuICAgIGlmICh0eXBlb2YgaGVhZGVyID09PSBcInN0cmluZ1wiXG4gICAgICAmJiB0aGlzLnJlYWR5U3RhdGUgPiB0aGlzLk9QRU5FRFxuICAgICAgJiYgcmVzcG9uc2VcbiAgICAgICYmIHJlc3BvbnNlLmhlYWRlcnNcbiAgICAgICYmIHJlc3BvbnNlLmhlYWRlcnNbaGVhZGVyLnRvTG93ZXJDYXNlKCldXG4gICAgICAmJiAhZXJyb3JGbGFnXG4gICAgKSB7XG4gICAgICByZXR1cm4gcmVzcG9uc2UuaGVhZGVyc1toZWFkZXIudG9Mb3dlckNhc2UoKV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH07XG5cbiAgLyoqXG4gICAqIEdldHMgYWxsIHRoZSByZXNwb25zZSBoZWFkZXJzLlxuICAgKlxuICAgKiBAcmV0dXJuIHN0cmluZyBBIHN0cmluZyB3aXRoIGFsbCByZXNwb25zZSBoZWFkZXJzIHNlcGFyYXRlZCBieSBDUitMRlxuICAgKi9cbiAgdGhpcy5nZXRBbGxSZXNwb25zZUhlYWRlcnMgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAodGhpcy5yZWFkeVN0YXRlIDwgdGhpcy5IRUFERVJTX1JFQ0VJVkVEIHx8IGVycm9yRmxhZykge1xuICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSBcIlwiO1xuXG4gICAgZm9yICh2YXIgaSBpbiByZXNwb25zZS5oZWFkZXJzKSB7XG4gICAgICAvLyBDb29raWUgaGVhZGVycyBhcmUgZXhjbHVkZWRcbiAgICAgIGlmIChpICE9PSBcInNldC1jb29raWVcIiAmJiBpICE9PSBcInNldC1jb29raWUyXCIpIHtcbiAgICAgICAgcmVzdWx0ICs9IGkgKyBcIjogXCIgKyByZXNwb25zZS5oZWFkZXJzW2ldICsgXCJcXHJcXG5cIjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdC5zdWJzdHIoMCwgcmVzdWx0Lmxlbmd0aCAtIDIpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBHZXRzIGEgcmVxdWVzdCBoZWFkZXJcbiAgICpcbiAgICogQHBhcmFtIHN0cmluZyBuYW1lIE5hbWUgb2YgaGVhZGVyIHRvIGdldFxuICAgKiBAcmV0dXJuIHN0cmluZyBSZXR1cm5zIHRoZSByZXF1ZXN0IGhlYWRlciBvciBlbXB0eSBzdHJpbmcgaWYgbm90IHNldFxuICAgKi9cbiAgdGhpcy5nZXRSZXF1ZXN0SGVhZGVyID0gZnVuY3Rpb24obmFtZSkge1xuICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gXCJzdHJpbmdcIiAmJiBoZWFkZXJzQ2FzZVtuYW1lLnRvTG93ZXJDYXNlKCldKSB7XG4gICAgICByZXR1cm4gaGVhZGVyc1toZWFkZXJzQ2FzZVtuYW1lLnRvTG93ZXJDYXNlKCldXTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJcIjtcbiAgfTtcblxuICAvKipcbiAgICogU2VuZHMgdGhlIHJlcXVlc3QgdG8gdGhlIHNlcnZlci5cbiAgICpcbiAgICogQHBhcmFtIHN0cmluZyBkYXRhIE9wdGlvbmFsIGRhdGEgdG8gc2VuZCBhcyByZXF1ZXN0IGJvZHkuXG4gICAqL1xuICB0aGlzLnNlbmQgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgaWYgKHRoaXMucmVhZHlTdGF0ZSAhPT0gdGhpcy5PUEVORUQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIklOVkFMSURfU1RBVEVfRVJSOiBjb25uZWN0aW9uIG11c3QgYmUgb3BlbmVkIGJlZm9yZSBzZW5kKCkgaXMgY2FsbGVkXCIpO1xuICAgIH1cblxuICAgIGlmIChzZW5kRmxhZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSU5WQUxJRF9TVEFURV9FUlI6IHNlbmQgaGFzIGFscmVhZHkgYmVlbiBjYWxsZWRcIik7XG4gICAgfVxuXG4gICAgdmFyIHNzbCA9IGZhbHNlLCBsb2NhbCA9IGZhbHNlO1xuICAgIHZhciB1cmwgPSBVcmwucGFyc2Uoc2V0dGluZ3MudXJsKTtcbiAgICB2YXIgaG9zdDtcbiAgICAvLyBEZXRlcm1pbmUgdGhlIHNlcnZlclxuICAgIHN3aXRjaCAodXJsLnByb3RvY29sKSB7XG4gICAgICBjYXNlIFwiaHR0cHM6XCI6XG4gICAgICAgIHNzbCA9IHRydWU7XG4gICAgICAgIC8vIFNTTCAmIG5vbi1TU0wgYm90aCBuZWVkIGhvc3QsIG5vIGJyZWFrIGhlcmUuXG4gICAgICBjYXNlIFwiaHR0cDpcIjpcbiAgICAgICAgaG9zdCA9IHVybC5ob3N0bmFtZTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgXCJmaWxlOlwiOlxuICAgICAgICBsb2NhbCA9IHRydWU7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgIGNhc2UgbnVsbDpcbiAgICAgIGNhc2UgXCJcIjpcbiAgICAgICAgaG9zdCA9IFwibG9jYWxob3N0XCI7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQcm90b2NvbCBub3Qgc3VwcG9ydGVkLlwiKTtcbiAgICB9XG5cbiAgICAvLyBMb2FkIGZpbGVzIG9mZiB0aGUgbG9jYWwgZmlsZXN5c3RlbSAoZmlsZTovLylcbiAgICBpZiAobG9jYWwpIHtcbiAgICAgIGlmIChzZXR0aW5ncy5tZXRob2QgIT09IFwiR0VUXCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiWE1MSHR0cFJlcXVlc3Q6IE9ubHkgR0VUIG1ldGhvZCBpcyBzdXBwb3J0ZWRcIik7XG4gICAgICB9XG5cbiAgICAgIGlmIChzZXR0aW5ncy5hc3luYykge1xuICAgICAgICBmcy5yZWFkRmlsZSh1cmwucGF0aG5hbWUsIFwidXRmOFwiLCBmdW5jdGlvbihlcnJvciwgZGF0YSkge1xuICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgc2VsZi5oYW5kbGVFcnJvcihlcnJvcik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNlbGYuc3RhdHVzID0gMjAwO1xuICAgICAgICAgICAgc2VsZi5yZXNwb25zZVRleHQgPSBkYXRhO1xuICAgICAgICAgICAgc2V0U3RhdGUoc2VsZi5ET05FKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICB0aGlzLnJlc3BvbnNlVGV4dCA9IGZzLnJlYWRGaWxlU3luYyh1cmwucGF0aG5hbWUsIFwidXRmOFwiKTtcbiAgICAgICAgICB0aGlzLnN0YXR1cyA9IDIwMDtcbiAgICAgICAgICBzZXRTdGF0ZShzZWxmLkRPTkUpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICB0aGlzLmhhbmRsZUVycm9yKGUpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBEZWZhdWx0IHRvIHBvcnQgODAuIElmIGFjY2Vzc2luZyBsb2NhbGhvc3Qgb24gYW5vdGhlciBwb3J0IGJlIHN1cmVcbiAgICAvLyB0byB1c2UgaHR0cDovL2xvY2FsaG9zdDpwb3J0L3BhdGhcbiAgICB2YXIgcG9ydCA9IHVybC5wb3J0IHx8IChzc2wgPyA0NDMgOiA4MCk7XG4gICAgLy8gQWRkIHF1ZXJ5IHN0cmluZyBpZiBvbmUgaXMgdXNlZFxuICAgIHZhciB1cmkgPSB1cmwucGF0aG5hbWUgKyAodXJsLnNlYXJjaCA/IHVybC5zZWFyY2ggOiBcIlwiKTtcblxuICAgIC8vIFNldCB0aGUgZGVmYXVsdHMgaWYgdGhleSBoYXZlbid0IGJlZW4gc2V0XG4gICAgZm9yICh2YXIgbmFtZSBpbiBkZWZhdWx0SGVhZGVycykge1xuICAgICAgaWYgKCFoZWFkZXJzQ2FzZVtuYW1lLnRvTG93ZXJDYXNlKCldKSB7XG4gICAgICAgIGhlYWRlcnNbbmFtZV0gPSBkZWZhdWx0SGVhZGVyc1tuYW1lXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZXQgdGhlIEhvc3QgaGVhZGVyIG9yIHRoZSBzZXJ2ZXIgbWF5IHJlamVjdCB0aGUgcmVxdWVzdFxuICAgIGhlYWRlcnMuSG9zdCA9IGhvc3Q7XG4gICAgaWYgKCEoKHNzbCAmJiBwb3J0ID09PSA0NDMpIHx8IHBvcnQgPT09IDgwKSkge1xuICAgICAgaGVhZGVycy5Ib3N0ICs9IFwiOlwiICsgdXJsLnBvcnQ7XG4gICAgfVxuXG4gICAgLy8gU2V0IEJhc2ljIEF1dGggaWYgbmVjZXNzYXJ5XG4gICAgaWYgKHNldHRpbmdzLnVzZXIpIHtcbiAgICAgIGlmICh0eXBlb2Ygc2V0dGluZ3MucGFzc3dvcmQgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgc2V0dGluZ3MucGFzc3dvcmQgPSBcIlwiO1xuICAgICAgfVxuICAgICAgdmFyIGF1dGhCdWYgPSBuZXcgQnVmZmVyKHNldHRpbmdzLnVzZXIgKyBcIjpcIiArIHNldHRpbmdzLnBhc3N3b3JkKTtcbiAgICAgIGhlYWRlcnMuQXV0aG9yaXphdGlvbiA9IFwiQmFzaWMgXCIgKyBhdXRoQnVmLnRvU3RyaW5nKFwiYmFzZTY0XCIpO1xuICAgIH1cblxuICAgIC8vIFNldCBjb250ZW50IGxlbmd0aCBoZWFkZXJcbiAgICBpZiAoc2V0dGluZ3MubWV0aG9kID09PSBcIkdFVFwiIHx8IHNldHRpbmdzLm1ldGhvZCA9PT0gXCJIRUFEXCIpIHtcbiAgICAgIGRhdGEgPSBudWxsO1xuICAgIH0gZWxzZSBpZiAoZGF0YSkge1xuICAgICAgaGVhZGVyc1tcIkNvbnRlbnQtTGVuZ3RoXCJdID0gQnVmZmVyLmlzQnVmZmVyKGRhdGEpID8gZGF0YS5sZW5ndGggOiBCdWZmZXIuYnl0ZUxlbmd0aChkYXRhKTtcblxuICAgICAgaWYgKCFoZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdKSB7XG4gICAgICAgIGhlYWRlcnNbXCJDb250ZW50LVR5cGVcIl0gPSBcInRleHQvcGxhaW47Y2hhcnNldD1VVEYtOFwiO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoc2V0dGluZ3MubWV0aG9kID09PSBcIlBPU1RcIikge1xuICAgICAgLy8gRm9yIGEgcG9zdCB3aXRoIG5vIGRhdGEgc2V0IENvbnRlbnQtTGVuZ3RoOiAwLlxuICAgICAgLy8gVGhpcyBpcyByZXF1aXJlZCBieSBidWdneSBzZXJ2ZXJzIHRoYXQgZG9uJ3QgbWVldCB0aGUgc3BlY3MuXG4gICAgICBoZWFkZXJzW1wiQ29udGVudC1MZW5ndGhcIl0gPSAwO1xuICAgIH1cblxuICAgIHZhciBvcHRpb25zID0ge1xuICAgICAgaG9zdDogaG9zdCxcbiAgICAgIHBvcnQ6IHBvcnQsXG4gICAgICBwYXRoOiB1cmksXG4gICAgICBtZXRob2Q6IHNldHRpbmdzLm1ldGhvZCxcbiAgICAgIGhlYWRlcnM6IGhlYWRlcnMsXG4gICAgICBhZ2VudDogZmFsc2UsXG4gICAgICB3aXRoQ3JlZGVudGlhbHM6IHNlbGYud2l0aENyZWRlbnRpYWxzXG4gICAgfTtcblxuICAgIC8vIFJlc2V0IGVycm9yIGZsYWdcbiAgICBlcnJvckZsYWcgPSBmYWxzZTtcblxuICAgIC8vIEhhbmRsZSBhc3luYyByZXF1ZXN0c1xuICAgIGlmIChzZXR0aW5ncy5hc3luYykge1xuICAgICAgLy8gVXNlIHRoZSBwcm9wZXIgcHJvdG9jb2xcbiAgICAgIHZhciBkb1JlcXVlc3QgPSBzc2wgPyBodHRwcy5yZXF1ZXN0IDogaHR0cC5yZXF1ZXN0O1xuXG4gICAgICAvLyBSZXF1ZXN0IGlzIGJlaW5nIHNlbnQsIHNldCBzZW5kIGZsYWdcbiAgICAgIHNlbmRGbGFnID0gdHJ1ZTtcblxuICAgICAgLy8gQXMgcGVyIHNwZWMsIHRoaXMgaXMgY2FsbGVkIGhlcmUgZm9yIGhpc3RvcmljYWwgcmVhc29ucy5cbiAgICAgIHNlbGYuZGlzcGF0Y2hFdmVudChcInJlYWR5c3RhdGVjaGFuZ2VcIik7XG5cbiAgICAgIC8vIEhhbmRsZXIgZm9yIHRoZSByZXNwb25zZVxuICAgICAgdmFyIHJlc3BvbnNlSGFuZGxlciA9IGZ1bmN0aW9uIHJlc3BvbnNlSGFuZGxlcihyZXNwKSB7XG4gICAgICAgIC8vIFNldCByZXNwb25zZSB2YXIgdG8gdGhlIHJlc3BvbnNlIHdlIGdvdCBiYWNrXG4gICAgICAgIC8vIFRoaXMgaXMgc28gaXQgcmVtYWlucyBhY2Nlc3NhYmxlIG91dHNpZGUgdGhpcyBzY29wZVxuICAgICAgICByZXNwb25zZSA9IHJlc3A7XG4gICAgICAgIC8vIENoZWNrIGZvciByZWRpcmVjdFxuICAgICAgICAvLyBAVE9ETyBQcmV2ZW50IGxvb3BlZCByZWRpcmVjdHNcbiAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDMwMSB8fCByZXNwb25zZS5zdGF0dXNDb2RlID09PSAzMDIgfHwgcmVzcG9uc2Uuc3RhdHVzQ29kZSA9PT0gMzAzIHx8IHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDMwNykge1xuICAgICAgICAgIC8vIENoYW5nZSBVUkwgdG8gdGhlIHJlZGlyZWN0IGxvY2F0aW9uXG4gICAgICAgICAgc2V0dGluZ3MudXJsID0gcmVzcG9uc2UuaGVhZGVycy5sb2NhdGlvbjtcbiAgICAgICAgICB2YXIgdXJsID0gVXJsLnBhcnNlKHNldHRpbmdzLnVybCk7XG4gICAgICAgICAgLy8gU2V0IGhvc3QgdmFyIGluIGNhc2UgaXQncyB1c2VkIGxhdGVyXG4gICAgICAgICAgaG9zdCA9IHVybC5ob3N0bmFtZTtcbiAgICAgICAgICAvLyBPcHRpb25zIGZvciB0aGUgbmV3IHJlcXVlc3RcbiAgICAgICAgICB2YXIgbmV3T3B0aW9ucyA9IHtcbiAgICAgICAgICAgIGhvc3RuYW1lOiB1cmwuaG9zdG5hbWUsXG4gICAgICAgICAgICBwb3J0OiB1cmwucG9ydCxcbiAgICAgICAgICAgIHBhdGg6IHVybC5wYXRoLFxuICAgICAgICAgICAgbWV0aG9kOiByZXNwb25zZS5zdGF0dXNDb2RlID09PSAzMDMgPyBcIkdFVFwiIDogc2V0dGluZ3MubWV0aG9kLFxuICAgICAgICAgICAgaGVhZGVyczogaGVhZGVycyxcbiAgICAgICAgICAgIHdpdGhDcmVkZW50aWFsczogc2VsZi53aXRoQ3JlZGVudGlhbHNcbiAgICAgICAgICB9O1xuXG4gICAgICAgICAgLy8gSXNzdWUgdGhlIG5ldyByZXF1ZXN0XG4gICAgICAgICAgcmVxdWVzdCA9IGRvUmVxdWVzdChuZXdPcHRpb25zLCByZXNwb25zZUhhbmRsZXIpLm9uKFwiZXJyb3JcIiwgZXJyb3JIYW5kbGVyKTtcbiAgICAgICAgICByZXF1ZXN0LmVuZCgpO1xuICAgICAgICAgIC8vIEBUT0RPIENoZWNrIGlmIGFuIFhIUiBldmVudCBuZWVkcyB0byBiZSBmaXJlZCBoZXJlXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzcG9uc2Uuc2V0RW5jb2RpbmcoXCJ1dGY4XCIpO1xuXG4gICAgICAgIHNldFN0YXRlKHNlbGYuSEVBREVSU19SRUNFSVZFRCk7XG4gICAgICAgIHNlbGYuc3RhdHVzID0gcmVzcG9uc2Uuc3RhdHVzQ29kZTtcblxuICAgICAgICByZXNwb25zZS5vbihcImRhdGFcIiwgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlcmUncyBzb21lIGRhdGFcbiAgICAgICAgICBpZiAoY2h1bmspIHtcbiAgICAgICAgICAgIHNlbGYucmVzcG9uc2VUZXh0ICs9IGNodW5rO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvLyBEb24ndCBlbWl0IHN0YXRlIGNoYW5nZXMgaWYgdGhlIGNvbm5lY3Rpb24gaGFzIGJlZW4gYWJvcnRlZC5cbiAgICAgICAgICBpZiAoc2VuZEZsYWcpIHtcbiAgICAgICAgICAgIHNldFN0YXRlKHNlbGYuTE9BRElORyk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXNwb25zZS5vbihcImVuZFwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICBpZiAoc2VuZEZsYWcpIHtcbiAgICAgICAgICAgIC8vIERpc2NhcmQgdGhlIGVuZCBldmVudCBpZiB0aGUgY29ubmVjdGlvbiBoYXMgYmVlbiBhYm9ydGVkXG4gICAgICAgICAgICBzZXRTdGF0ZShzZWxmLkRPTkUpO1xuICAgICAgICAgICAgc2VuZEZsYWcgPSBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJlc3BvbnNlLm9uKFwiZXJyb3JcIiwgZnVuY3Rpb24oZXJyb3IpIHtcbiAgICAgICAgICBzZWxmLmhhbmRsZUVycm9yKGVycm9yKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICAvLyBFcnJvciBoYW5kbGVyIGZvciB0aGUgcmVxdWVzdFxuICAgICAgdmFyIGVycm9ySGFuZGxlciA9IGZ1bmN0aW9uIGVycm9ySGFuZGxlcihlcnJvcikge1xuICAgICAgICBzZWxmLmhhbmRsZUVycm9yKGVycm9yKTtcbiAgICAgIH07XG5cbiAgICAgIC8vIENyZWF0ZSB0aGUgcmVxdWVzdFxuICAgICAgcmVxdWVzdCA9IGRvUmVxdWVzdChvcHRpb25zLCByZXNwb25zZUhhbmRsZXIpLm9uKFwiZXJyb3JcIiwgZXJyb3JIYW5kbGVyKTtcblxuICAgICAgLy8gTm9kZSAwLjQgYW5kIGxhdGVyIHdvbid0IGFjY2VwdCBlbXB0eSBkYXRhLiBNYWtlIHN1cmUgaXQncyBuZWVkZWQuXG4gICAgICBpZiAoZGF0YSkge1xuICAgICAgICByZXF1ZXN0LndyaXRlKGRhdGEpO1xuICAgICAgfVxuXG4gICAgICByZXF1ZXN0LmVuZCgpO1xuXG4gICAgICBzZWxmLmRpc3BhdGNoRXZlbnQoXCJsb2Fkc3RhcnRcIik7XG4gICAgfSBlbHNlIHsgLy8gU3luY2hyb25vdXNcbiAgICAgIC8vIENyZWF0ZSBhIHRlbXBvcmFyeSBmaWxlIGZvciBjb21tdW5pY2F0aW9uIHdpdGggdGhlIG90aGVyIE5vZGUgcHJvY2Vzc1xuICAgICAgdmFyIGNvbnRlbnRGaWxlID0gXCIubm9kZS14bWxodHRwcmVxdWVzdC1jb250ZW50LVwiICsgcHJvY2Vzcy5waWQ7XG4gICAgICB2YXIgc3luY0ZpbGUgPSBcIi5ub2RlLXhtbGh0dHByZXF1ZXN0LXN5bmMtXCIgKyBwcm9jZXNzLnBpZDtcbiAgICAgIGZzLndyaXRlRmlsZVN5bmMoc3luY0ZpbGUsIFwiXCIsIFwidXRmOFwiKTtcbiAgICAgIC8vIFRoZSBhc3luYyByZXF1ZXN0IHRoZSBvdGhlciBOb2RlIHByb2Nlc3MgZXhlY3V0ZXNcbiAgICAgIHZhciBleGVjU3RyaW5nID0gXCJ2YXIgaHR0cCA9IHJlcXVpcmUoJ2h0dHAnKSwgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpLCBmcyA9IHJlcXVpcmUoJ2ZzJyk7XCJcbiAgICAgICAgKyBcInZhciBkb1JlcXVlc3QgPSBodHRwXCIgKyAoc3NsID8gXCJzXCIgOiBcIlwiKSArIFwiLnJlcXVlc3Q7XCJcbiAgICAgICAgKyBcInZhciBvcHRpb25zID0gXCIgKyBKU09OLnN0cmluZ2lmeShvcHRpb25zKSArIFwiO1wiXG4gICAgICAgICsgXCJ2YXIgcmVzcG9uc2VUZXh0ID0gJyc7XCJcbiAgICAgICAgKyBcInZhciByZXEgPSBkb1JlcXVlc3Qob3B0aW9ucywgZnVuY3Rpb24ocmVzcG9uc2UpIHtcIlxuICAgICAgICArIFwicmVzcG9uc2Uuc2V0RW5jb2RpbmcoJ3V0ZjgnKTtcIlxuICAgICAgICArIFwicmVzcG9uc2Uub24oJ2RhdGEnLCBmdW5jdGlvbihjaHVuaykge1wiXG4gICAgICAgICsgXCIgIHJlc3BvbnNlVGV4dCArPSBjaHVuaztcIlxuICAgICAgICArIFwifSk7XCJcbiAgICAgICAgKyBcInJlc3BvbnNlLm9uKCdlbmQnLCBmdW5jdGlvbigpIHtcIlxuICAgICAgICArIFwiZnMud3JpdGVGaWxlU3luYygnXCIgKyBjb250ZW50RmlsZSArIFwiJywgSlNPTi5zdHJpbmdpZnkoe2VycjogbnVsbCwgZGF0YToge3N0YXR1c0NvZGU6IHJlc3BvbnNlLnN0YXR1c0NvZGUsIGhlYWRlcnM6IHJlc3BvbnNlLmhlYWRlcnMsIHRleHQ6IHJlc3BvbnNlVGV4dH19KSwgJ3V0ZjgnKTtcIlxuICAgICAgICArIFwiZnMudW5saW5rU3luYygnXCIgKyBzeW5jRmlsZSArIFwiJyk7XCJcbiAgICAgICAgKyBcIn0pO1wiXG4gICAgICAgICsgXCJyZXNwb25zZS5vbignZXJyb3InLCBmdW5jdGlvbihlcnJvcikge1wiXG4gICAgICAgICsgXCJmcy53cml0ZUZpbGVTeW5jKCdcIiArIGNvbnRlbnRGaWxlICsgXCInLCBKU09OLnN0cmluZ2lmeSh7ZXJyOiBlcnJvcn0pLCAndXRmOCcpO1wiXG4gICAgICAgICsgXCJmcy51bmxpbmtTeW5jKCdcIiArIHN5bmNGaWxlICsgXCInKTtcIlxuICAgICAgICArIFwifSk7XCJcbiAgICAgICAgKyBcIn0pLm9uKCdlcnJvcicsIGZ1bmN0aW9uKGVycm9yKSB7XCJcbiAgICAgICAgKyBcImZzLndyaXRlRmlsZVN5bmMoJ1wiICsgY29udGVudEZpbGUgKyBcIicsIEpTT04uc3RyaW5naWZ5KHtlcnI6IGVycm9yfSksICd1dGY4Jyk7XCJcbiAgICAgICAgKyBcImZzLnVubGlua1N5bmMoJ1wiICsgc3luY0ZpbGUgKyBcIicpO1wiXG4gICAgICAgICsgXCJ9KTtcIlxuICAgICAgICArIChkYXRhID8gXCJyZXEud3JpdGUoJ1wiICsgSlNPTi5zdHJpbmdpZnkoZGF0YSkuc2xpY2UoMSwtMSkucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpICsgXCInKTtcIjpcIlwiKVxuICAgICAgICArIFwicmVxLmVuZCgpO1wiO1xuICAgICAgLy8gU3RhcnQgdGhlIG90aGVyIE5vZGUgUHJvY2VzcywgZXhlY3V0aW5nIHRoaXMgc3RyaW5nXG4gICAgICB2YXIgc3luY1Byb2MgPSBzcGF3bihwcm9jZXNzLmFyZ3ZbMF0sIFtcIi1lXCIsIGV4ZWNTdHJpbmddKTtcbiAgICAgIHdoaWxlKGZzLmV4aXN0c1N5bmMoc3luY0ZpbGUpKSB7XG4gICAgICAgIC8vIFdhaXQgd2hpbGUgdGhlIHN5bmMgZmlsZSBpcyBlbXB0eVxuICAgICAgfVxuICAgICAgdmFyIHJlc3AgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhjb250ZW50RmlsZSwgJ3V0ZjgnKSk7XG4gICAgICAvLyBLaWxsIHRoZSBjaGlsZCBwcm9jZXNzIG9uY2UgdGhlIGZpbGUgaGFzIGRhdGFcbiAgICAgIHN5bmNQcm9jLnN0ZGluLmVuZCgpO1xuICAgICAgLy8gUmVtb3ZlIHRoZSB0ZW1wb3JhcnkgZmlsZVxuICAgICAgZnMudW5saW5rU3luYyhjb250ZW50RmlsZSk7XG5cbiAgICAgIGlmIChyZXNwLmVycikge1xuICAgICAgICBzZWxmLmhhbmRsZUVycm9yKHJlc3AuZXJyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3BvbnNlID0gcmVzcC5kYXRhO1xuICAgICAgICBzZWxmLnN0YXR1cyA9IHJlc3AuZGF0YS5zdGF0dXNDb2RlO1xuICAgICAgICBzZWxmLnJlc3BvbnNlVGV4dCA9IHJlc3AuZGF0YS50ZXh0O1xuICAgICAgICBzZXRTdGF0ZShzZWxmLkRPTkUpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gYW4gZXJyb3IgaXMgZW5jb3VudGVyZWQgdG8gZGVhbCB3aXRoIGl0LlxuICAgKi9cbiAgdGhpcy5oYW5kbGVFcnJvciA9IGZ1bmN0aW9uKGVycm9yKSB7XG4gICAgdGhpcy5zdGF0dXMgPSAwO1xuICAgIHRoaXMuc3RhdHVzVGV4dCA9IGVycm9yO1xuICAgIHRoaXMucmVzcG9uc2VUZXh0ID0gZXJyb3Iuc3RhY2s7XG4gICAgZXJyb3JGbGFnID0gdHJ1ZTtcbiAgICBzZXRTdGF0ZSh0aGlzLkRPTkUpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudCgnZXJyb3InKTtcbiAgfTtcblxuICAvKipcbiAgICogQWJvcnRzIGEgcmVxdWVzdC5cbiAgICovXG4gIHRoaXMuYWJvcnQgPSBmdW5jdGlvbigpIHtcbiAgICBpZiAocmVxdWVzdCkge1xuICAgICAgcmVxdWVzdC5hYm9ydCgpO1xuICAgICAgcmVxdWVzdCA9IG51bGw7XG4gICAgfVxuXG4gICAgaGVhZGVycyA9IGRlZmF1bHRIZWFkZXJzO1xuICAgIHRoaXMuc3RhdHVzID0gMDtcbiAgICB0aGlzLnJlc3BvbnNlVGV4dCA9IFwiXCI7XG4gICAgdGhpcy5yZXNwb25zZVhNTCA9IFwiXCI7XG5cbiAgICBlcnJvckZsYWcgPSB0cnVlO1xuXG4gICAgaWYgKHRoaXMucmVhZHlTdGF0ZSAhPT0gdGhpcy5VTlNFTlRcbiAgICAgICAgJiYgKHRoaXMucmVhZHlTdGF0ZSAhPT0gdGhpcy5PUEVORUQgfHwgc2VuZEZsYWcpXG4gICAgICAgICYmIHRoaXMucmVhZHlTdGF0ZSAhPT0gdGhpcy5ET05FKSB7XG4gICAgICBzZW5kRmxhZyA9IGZhbHNlO1xuICAgICAgc2V0U3RhdGUodGhpcy5ET05FKTtcbiAgICB9XG4gICAgdGhpcy5yZWFkeVN0YXRlID0gdGhpcy5VTlNFTlQ7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KCdhYm9ydCcpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBZGRzIGFuIGV2ZW50IGxpc3RlbmVyLiBQcmVmZXJyZWQgbWV0aG9kIG9mIGJpbmRpbmcgdG8gZXZlbnRzLlxuICAgKi9cbiAgdGhpcy5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24oZXZlbnQsIGNhbGxiYWNrKSB7XG4gICAgaWYgKCEoZXZlbnQgaW4gbGlzdGVuZXJzKSkge1xuICAgICAgbGlzdGVuZXJzW2V2ZW50XSA9IFtdO1xuICAgIH1cbiAgICAvLyBDdXJyZW50bHkgYWxsb3dzIGR1cGxpY2F0ZSBjYWxsYmFja3MuIFNob3VsZCBpdD9cbiAgICBsaXN0ZW5lcnNbZXZlbnRdLnB1c2goY2FsbGJhY2spO1xuICB9O1xuXG4gIC8qKlxuICAgKiBSZW1vdmUgYW4gZXZlbnQgY2FsbGJhY2sgdGhhdCBoYXMgYWxyZWFkeSBiZWVuIGJvdW5kLlxuICAgKiBPbmx5IHdvcmtzIG9uIHRoZSBtYXRjaGluZyBmdW5jaXRvbiwgY2Fubm90IGJlIGEgY29weS5cbiAgICovXG4gIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKGV2ZW50LCBjYWxsYmFjaykge1xuICAgIGlmIChldmVudCBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgIC8vIEZpbHRlciB3aWxsIHJldHVybiBhIG5ldyBhcnJheSB3aXRoIHRoZSBjYWxsYmFjayByZW1vdmVkXG4gICAgICBsaXN0ZW5lcnNbZXZlbnRdID0gbGlzdGVuZXJzW2V2ZW50XS5maWx0ZXIoZnVuY3Rpb24oZXYpIHtcbiAgICAgICAgcmV0dXJuIGV2ICE9PSBjYWxsYmFjaztcbiAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogRGlzcGF0Y2ggYW55IGV2ZW50cywgaW5jbHVkaW5nIGJvdGggXCJvblwiIG1ldGhvZHMgYW5kIGV2ZW50cyBhdHRhY2hlZCB1c2luZyBhZGRFdmVudExpc3RlbmVyLlxuICAgKi9cbiAgdGhpcy5kaXNwYXRjaEV2ZW50ID0gZnVuY3Rpb24oZXZlbnQpIHtcbiAgICBpZiAodHlwZW9mIHNlbGZbXCJvblwiICsgZXZlbnRdID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIHNlbGZbXCJvblwiICsgZXZlbnRdKCk7XG4gICAgfVxuICAgIGlmIChldmVudCBpbiBsaXN0ZW5lcnMpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBsaXN0ZW5lcnNbZXZlbnRdLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgIGxpc3RlbmVyc1tldmVudF1baV0uY2FsbChzZWxmKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIENoYW5nZXMgcmVhZHlTdGF0ZSBhbmQgY2FsbHMgb25yZWFkeXN0YXRlY2hhbmdlLlxuICAgKlxuICAgKiBAcGFyYW0gaW50IHN0YXRlIE5ldyBzdGF0ZVxuICAgKi9cbiAgdmFyIHNldFN0YXRlID0gZnVuY3Rpb24oc3RhdGUpIHtcbiAgICBpZiAoc3RhdGUgPT0gc2VsZi5MT0FESU5HIHx8IHNlbGYucmVhZHlTdGF0ZSAhPT0gc3RhdGUpIHtcbiAgICAgIHNlbGYucmVhZHlTdGF0ZSA9IHN0YXRlO1xuXG4gICAgICBpZiAoc2V0dGluZ3MuYXN5bmMgfHwgc2VsZi5yZWFkeVN0YXRlIDwgc2VsZi5PUEVORUQgfHwgc2VsZi5yZWFkeVN0YXRlID09PSBzZWxmLkRPTkUpIHtcbiAgICAgICAgc2VsZi5kaXNwYXRjaEV2ZW50KFwicmVhZHlzdGF0ZWNoYW5nZVwiKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNlbGYucmVhZHlTdGF0ZSA9PT0gc2VsZi5ET05FICYmICFlcnJvckZsYWcpIHtcbiAgICAgICAgc2VsZi5kaXNwYXRjaEV2ZW50KFwibG9hZFwiKTtcbiAgICAgICAgLy8gQFRPRE8gZmlndXJlIG91dCBJbnNwZWN0b3JJbnN0cnVtZW50YXRpb246OmRpZExvYWRYSFIoY29va2llKVxuICAgICAgICBzZWxmLmRpc3BhdGNoRXZlbnQoXCJsb2FkZW5kXCIpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGV4dGVuZFxuXG52YXIgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xuXG5mdW5jdGlvbiBleHRlbmQoKSB7XG4gICAgdmFyIHRhcmdldCA9IHt9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldXG5cbiAgICAgICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRhcmdldFxufVxuIl19 diff --git a/assets/js/tracker.js b/assets/dist/js/tracker.js similarity index 100% rename from assets/js/tracker.js rename to assets/dist/js/tracker.js diff --git a/assets/src/img/country-flags/ad.png b/assets/src/img/country-flags/ad.png new file mode 100644 index 0000000..ae7b64c Binary files /dev/null and b/assets/src/img/country-flags/ad.png differ diff --git a/assets/src/img/country-flags/ae.png b/assets/src/img/country-flags/ae.png new file mode 100644 index 0000000..428fd79 Binary files /dev/null and b/assets/src/img/country-flags/ae.png differ diff --git a/assets/src/img/country-flags/af.png b/assets/src/img/country-flags/af.png new file mode 100644 index 0000000..04804e6 Binary files /dev/null and b/assets/src/img/country-flags/af.png differ diff --git a/assets/src/img/country-flags/ag.png b/assets/src/img/country-flags/ag.png new file mode 100644 index 0000000..df8c629 Binary files /dev/null and b/assets/src/img/country-flags/ag.png differ diff --git a/assets/src/img/country-flags/ai.png b/assets/src/img/country-flags/ai.png new file mode 100644 index 0000000..33ade6d Binary files /dev/null and b/assets/src/img/country-flags/ai.png differ diff --git a/assets/src/img/country-flags/al.png b/assets/src/img/country-flags/al.png new file mode 100644 index 0000000..47d3354 Binary files /dev/null and b/assets/src/img/country-flags/al.png differ diff --git a/assets/src/img/country-flags/am.png b/assets/src/img/country-flags/am.png new file mode 100644 index 0000000..03f94ab Binary files /dev/null and b/assets/src/img/country-flags/am.png differ diff --git a/assets/src/img/country-flags/ao.png b/assets/src/img/country-flags/ao.png new file mode 100644 index 0000000..385a334 Binary files /dev/null and b/assets/src/img/country-flags/ao.png differ diff --git a/assets/src/img/country-flags/ar.png b/assets/src/img/country-flags/ar.png new file mode 100644 index 0000000..a7e2412 Binary files /dev/null and b/assets/src/img/country-flags/ar.png differ diff --git a/assets/src/img/country-flags/as.png b/assets/src/img/country-flags/as.png new file mode 100644 index 0000000..b8f967a Binary files /dev/null and b/assets/src/img/country-flags/as.png differ diff --git a/assets/src/img/country-flags/at.png b/assets/src/img/country-flags/at.png new file mode 100644 index 0000000..d3b2b2d Binary files /dev/null and b/assets/src/img/country-flags/at.png differ diff --git a/assets/src/img/country-flags/au.png b/assets/src/img/country-flags/au.png new file mode 100644 index 0000000..22b082c Binary files /dev/null and b/assets/src/img/country-flags/au.png differ diff --git a/assets/src/img/country-flags/aw.png b/assets/src/img/country-flags/aw.png new file mode 100644 index 0000000..980c144 Binary files /dev/null and b/assets/src/img/country-flags/aw.png differ diff --git a/assets/src/img/country-flags/ax.png b/assets/src/img/country-flags/ax.png new file mode 100644 index 0000000..21213a4 Binary files /dev/null and b/assets/src/img/country-flags/ax.png differ diff --git a/assets/src/img/country-flags/az.png b/assets/src/img/country-flags/az.png new file mode 100644 index 0000000..caeaf19 Binary files /dev/null and b/assets/src/img/country-flags/az.png differ diff --git a/assets/src/img/country-flags/ba.png b/assets/src/img/country-flags/ba.png new file mode 100644 index 0000000..d43d4b0 Binary files /dev/null and b/assets/src/img/country-flags/ba.png differ diff --git a/assets/src/img/country-flags/bb.png b/assets/src/img/country-flags/bb.png new file mode 100644 index 0000000..36140b9 Binary files /dev/null and b/assets/src/img/country-flags/bb.png differ diff --git a/assets/src/img/country-flags/bd.png b/assets/src/img/country-flags/bd.png new file mode 100644 index 0000000..63daa63 Binary files /dev/null and b/assets/src/img/country-flags/bd.png differ diff --git a/assets/src/img/country-flags/be.png b/assets/src/img/country-flags/be.png new file mode 100644 index 0000000..2db4fd7 Binary files /dev/null and b/assets/src/img/country-flags/be.png differ diff --git a/assets/src/img/country-flags/bf.png b/assets/src/img/country-flags/bf.png new file mode 100644 index 0000000..c3ac9da Binary files /dev/null and b/assets/src/img/country-flags/bf.png differ diff --git a/assets/src/img/country-flags/bg.png b/assets/src/img/country-flags/bg.png new file mode 100644 index 0000000..5bde564 Binary files /dev/null and b/assets/src/img/country-flags/bg.png differ diff --git a/assets/src/img/country-flags/bh.png b/assets/src/img/country-flags/bh.png new file mode 100644 index 0000000..d08c757 Binary files /dev/null and b/assets/src/img/country-flags/bh.png differ diff --git a/assets/src/img/country-flags/bi.png b/assets/src/img/country-flags/bi.png new file mode 100644 index 0000000..6ba603c Binary files /dev/null and b/assets/src/img/country-flags/bi.png differ diff --git a/assets/src/img/country-flags/bj.png b/assets/src/img/country-flags/bj.png new file mode 100644 index 0000000..aaee839 Binary files /dev/null and b/assets/src/img/country-flags/bj.png differ diff --git a/assets/src/img/country-flags/bm.png b/assets/src/img/country-flags/bm.png new file mode 100644 index 0000000..55a3912 Binary files /dev/null and b/assets/src/img/country-flags/bm.png differ diff --git a/assets/src/img/country-flags/bn.png b/assets/src/img/country-flags/bn.png new file mode 100644 index 0000000..a3a30c8 Binary files /dev/null and b/assets/src/img/country-flags/bn.png differ diff --git a/assets/src/img/country-flags/bo.png b/assets/src/img/country-flags/bo.png new file mode 100644 index 0000000..ef3d226 Binary files /dev/null and b/assets/src/img/country-flags/bo.png differ diff --git a/assets/src/img/country-flags/br.png b/assets/src/img/country-flags/br.png new file mode 100644 index 0000000..6861552 Binary files /dev/null and b/assets/src/img/country-flags/br.png differ diff --git a/assets/src/img/country-flags/bs.png b/assets/src/img/country-flags/bs.png new file mode 100644 index 0000000..e89e728 Binary files /dev/null and b/assets/src/img/country-flags/bs.png differ diff --git a/assets/src/img/country-flags/bt.png b/assets/src/img/country-flags/bt.png new file mode 100644 index 0000000..4bb90bf Binary files /dev/null and b/assets/src/img/country-flags/bt.png differ diff --git a/assets/src/img/country-flags/bw.png b/assets/src/img/country-flags/bw.png new file mode 100644 index 0000000..0c5e0c9 Binary files /dev/null and b/assets/src/img/country-flags/bw.png differ diff --git a/assets/src/img/country-flags/by.png b/assets/src/img/country-flags/by.png new file mode 100644 index 0000000..1087934 Binary files /dev/null and b/assets/src/img/country-flags/by.png differ diff --git a/assets/src/img/country-flags/bz.png b/assets/src/img/country-flags/bz.png new file mode 100644 index 0000000..7226484 Binary files /dev/null and b/assets/src/img/country-flags/bz.png differ diff --git a/assets/src/img/country-flags/ca.png b/assets/src/img/country-flags/ca.png new file mode 100644 index 0000000..6d8d6f5 Binary files /dev/null and b/assets/src/img/country-flags/ca.png differ diff --git a/assets/src/img/country-flags/cc.png b/assets/src/img/country-flags/cc.png new file mode 100644 index 0000000..da5bd32 Binary files /dev/null and b/assets/src/img/country-flags/cc.png differ diff --git a/assets/src/img/country-flags/cd.png b/assets/src/img/country-flags/cd.png new file mode 100644 index 0000000..9ac55f1 Binary files /dev/null and b/assets/src/img/country-flags/cd.png differ diff --git a/assets/src/img/country-flags/cf.png b/assets/src/img/country-flags/cf.png new file mode 100644 index 0000000..f2feb8a Binary files /dev/null and b/assets/src/img/country-flags/cf.png differ diff --git a/assets/src/img/country-flags/cg.png b/assets/src/img/country-flags/cg.png new file mode 100644 index 0000000..69cb8be Binary files /dev/null and b/assets/src/img/country-flags/cg.png differ diff --git a/assets/src/img/country-flags/ch.png b/assets/src/img/country-flags/ch.png new file mode 100644 index 0000000..601e8f3 Binary files /dev/null and b/assets/src/img/country-flags/ch.png differ diff --git a/assets/src/img/country-flags/ci.png b/assets/src/img/country-flags/ci.png new file mode 100644 index 0000000..170ceac Binary files /dev/null and b/assets/src/img/country-flags/ci.png differ diff --git a/assets/src/img/country-flags/ck.png b/assets/src/img/country-flags/ck.png new file mode 100644 index 0000000..12a4fe3 Binary files /dev/null and b/assets/src/img/country-flags/ck.png differ diff --git a/assets/src/img/country-flags/cl.png b/assets/src/img/country-flags/cl.png new file mode 100644 index 0000000..ecfb097 Binary files /dev/null and b/assets/src/img/country-flags/cl.png differ diff --git a/assets/src/img/country-flags/cm.png b/assets/src/img/country-flags/cm.png new file mode 100644 index 0000000..4008a23 Binary files /dev/null and b/assets/src/img/country-flags/cm.png differ diff --git a/assets/src/img/country-flags/cn.png b/assets/src/img/country-flags/cn.png new file mode 100644 index 0000000..8a8e879 Binary files /dev/null and b/assets/src/img/country-flags/cn.png differ diff --git a/assets/src/img/country-flags/co.png b/assets/src/img/country-flags/co.png new file mode 100644 index 0000000..3103d11 Binary files /dev/null and b/assets/src/img/country-flags/co.png differ diff --git a/assets/src/img/country-flags/cr.png b/assets/src/img/country-flags/cr.png new file mode 100644 index 0000000..b2c302e Binary files /dev/null and b/assets/src/img/country-flags/cr.png differ diff --git a/assets/src/img/country-flags/cu.png b/assets/src/img/country-flags/cu.png new file mode 100644 index 0000000..8aea838 Binary files /dev/null and b/assets/src/img/country-flags/cu.png differ diff --git a/assets/src/img/country-flags/cv.png b/assets/src/img/country-flags/cv.png new file mode 100644 index 0000000..1ffceb9 Binary files /dev/null and b/assets/src/img/country-flags/cv.png differ diff --git a/assets/src/img/country-flags/cw.png b/assets/src/img/country-flags/cw.png new file mode 100644 index 0000000..27028c2 Binary files /dev/null and b/assets/src/img/country-flags/cw.png differ diff --git a/assets/src/img/country-flags/cx.png b/assets/src/img/country-flags/cx.png new file mode 100644 index 0000000..451a039 Binary files /dev/null and b/assets/src/img/country-flags/cx.png differ diff --git a/assets/src/img/country-flags/cy.png b/assets/src/img/country-flags/cy.png new file mode 100644 index 0000000..ce3e1a3 Binary files /dev/null and b/assets/src/img/country-flags/cy.png differ diff --git a/assets/src/img/country-flags/cz.png b/assets/src/img/country-flags/cz.png new file mode 100644 index 0000000..adfa272 Binary files /dev/null and b/assets/src/img/country-flags/cz.png differ diff --git a/assets/src/img/country-flags/de.png b/assets/src/img/country-flags/de.png new file mode 100644 index 0000000..8e22c8a Binary files /dev/null and b/assets/src/img/country-flags/de.png differ diff --git a/assets/src/img/country-flags/dj.png b/assets/src/img/country-flags/dj.png new file mode 100644 index 0000000..288f42c Binary files /dev/null and b/assets/src/img/country-flags/dj.png differ diff --git a/assets/src/img/country-flags/dk.png b/assets/src/img/country-flags/dk.png new file mode 100644 index 0000000..50e2919 Binary files /dev/null and b/assets/src/img/country-flags/dk.png differ diff --git a/assets/src/img/country-flags/dm.png b/assets/src/img/country-flags/dm.png new file mode 100644 index 0000000..89101a6 Binary files /dev/null and b/assets/src/img/country-flags/dm.png differ diff --git a/assets/src/img/country-flags/do.png b/assets/src/img/country-flags/do.png new file mode 100644 index 0000000..b7a6f4c Binary files /dev/null and b/assets/src/img/country-flags/do.png differ diff --git a/assets/src/img/country-flags/dz.png b/assets/src/img/country-flags/dz.png new file mode 100644 index 0000000..1ab21fd Binary files /dev/null and b/assets/src/img/country-flags/dz.png differ diff --git a/assets/src/img/country-flags/ec.png b/assets/src/img/country-flags/ec.png new file mode 100644 index 0000000..84ef4d4 Binary files /dev/null and b/assets/src/img/country-flags/ec.png differ diff --git a/assets/src/img/country-flags/ee.png b/assets/src/img/country-flags/ee.png new file mode 100644 index 0000000..7f506ce Binary files /dev/null and b/assets/src/img/country-flags/ee.png differ diff --git a/assets/src/img/country-flags/eg.png b/assets/src/img/country-flags/eg.png new file mode 100644 index 0000000..e5ab4af Binary files /dev/null and b/assets/src/img/country-flags/eg.png differ diff --git a/assets/src/img/country-flags/er.png b/assets/src/img/country-flags/er.png new file mode 100644 index 0000000..542ea41 Binary files /dev/null and b/assets/src/img/country-flags/er.png differ diff --git a/assets/src/img/country-flags/es.png b/assets/src/img/country-flags/es.png new file mode 100644 index 0000000..e018dd7 Binary files /dev/null and b/assets/src/img/country-flags/es.png differ diff --git a/assets/src/img/country-flags/et.png b/assets/src/img/country-flags/et.png new file mode 100644 index 0000000..5fba1f6 Binary files /dev/null and b/assets/src/img/country-flags/et.png differ diff --git a/assets/src/img/country-flags/fi.png b/assets/src/img/country-flags/fi.png new file mode 100644 index 0000000..cd6eb45 Binary files /dev/null and b/assets/src/img/country-flags/fi.png differ diff --git a/assets/src/img/country-flags/fj.png b/assets/src/img/country-flags/fj.png new file mode 100644 index 0000000..1bdd633 Binary files /dev/null and b/assets/src/img/country-flags/fj.png differ diff --git a/assets/src/img/country-flags/fk.png b/assets/src/img/country-flags/fk.png new file mode 100644 index 0000000..51858b7 Binary files /dev/null and b/assets/src/img/country-flags/fk.png differ diff --git a/assets/src/img/country-flags/fm.png b/assets/src/img/country-flags/fm.png new file mode 100644 index 0000000..01b76fa Binary files /dev/null and b/assets/src/img/country-flags/fm.png differ diff --git a/assets/src/img/country-flags/fo.png b/assets/src/img/country-flags/fo.png new file mode 100644 index 0000000..0462b42 Binary files /dev/null and b/assets/src/img/country-flags/fo.png differ diff --git a/assets/src/img/country-flags/fr.png b/assets/src/img/country-flags/fr.png new file mode 100644 index 0000000..b8e120b Binary files /dev/null and b/assets/src/img/country-flags/fr.png differ diff --git a/assets/src/img/country-flags/ga.png b/assets/src/img/country-flags/ga.png new file mode 100644 index 0000000..838b34b Binary files /dev/null and b/assets/src/img/country-flags/ga.png differ diff --git a/assets/src/img/country-flags/gb.png b/assets/src/img/country-flags/gb.png new file mode 100644 index 0000000..53fdf1b Binary files /dev/null and b/assets/src/img/country-flags/gb.png differ diff --git a/assets/src/img/country-flags/gd.png b/assets/src/img/country-flags/gd.png new file mode 100644 index 0000000..116e0f1 Binary files /dev/null and b/assets/src/img/country-flags/gd.png differ diff --git a/assets/src/img/country-flags/ge.png b/assets/src/img/country-flags/ge.png new file mode 100644 index 0000000..7948ed4 Binary files /dev/null and b/assets/src/img/country-flags/ge.png differ diff --git a/assets/src/img/country-flags/gg.png b/assets/src/img/country-flags/gg.png new file mode 100644 index 0000000..1700cce Binary files /dev/null and b/assets/src/img/country-flags/gg.png differ diff --git a/assets/src/img/country-flags/gh.png b/assets/src/img/country-flags/gh.png new file mode 100644 index 0000000..f808603 Binary files /dev/null and b/assets/src/img/country-flags/gh.png differ diff --git a/assets/src/img/country-flags/gi.png b/assets/src/img/country-flags/gi.png new file mode 100644 index 0000000..cd9a54d Binary files /dev/null and b/assets/src/img/country-flags/gi.png differ diff --git a/assets/src/img/country-flags/gl.png b/assets/src/img/country-flags/gl.png new file mode 100644 index 0000000..0fadabf Binary files /dev/null and b/assets/src/img/country-flags/gl.png differ diff --git a/assets/src/img/country-flags/gm.png b/assets/src/img/country-flags/gm.png new file mode 100644 index 0000000..cf01f84 Binary files /dev/null and b/assets/src/img/country-flags/gm.png differ diff --git a/assets/src/img/country-flags/gn.png b/assets/src/img/country-flags/gn.png new file mode 100644 index 0000000..12812d5 Binary files /dev/null and b/assets/src/img/country-flags/gn.png differ diff --git a/assets/src/img/country-flags/gq.png b/assets/src/img/country-flags/gq.png new file mode 100644 index 0000000..cea6978 Binary files /dev/null and b/assets/src/img/country-flags/gq.png differ diff --git a/assets/src/img/country-flags/gr.png b/assets/src/img/country-flags/gr.png new file mode 100644 index 0000000..f1bcc67 Binary files /dev/null and b/assets/src/img/country-flags/gr.png differ diff --git a/assets/src/img/country-flags/gs.png b/assets/src/img/country-flags/gs.png new file mode 100644 index 0000000..8f01756 Binary files /dev/null and b/assets/src/img/country-flags/gs.png differ diff --git a/assets/src/img/country-flags/gt.png b/assets/src/img/country-flags/gt.png new file mode 100644 index 0000000..8429f0e Binary files /dev/null and b/assets/src/img/country-flags/gt.png differ diff --git a/assets/src/img/country-flags/gu.png b/assets/src/img/country-flags/gu.png new file mode 100644 index 0000000..e06f96c Binary files /dev/null and b/assets/src/img/country-flags/gu.png differ diff --git a/assets/src/img/country-flags/gw.png b/assets/src/img/country-flags/gw.png new file mode 100644 index 0000000..0883b13 Binary files /dev/null and b/assets/src/img/country-flags/gw.png differ diff --git a/assets/src/img/country-flags/gy.png b/assets/src/img/country-flags/gy.png new file mode 100644 index 0000000..982cc7f Binary files /dev/null and b/assets/src/img/country-flags/gy.png differ diff --git a/assets/src/img/country-flags/hk.png b/assets/src/img/country-flags/hk.png new file mode 100644 index 0000000..3ac4c9b Binary files /dev/null and b/assets/src/img/country-flags/hk.png differ diff --git a/assets/src/img/country-flags/hn.png b/assets/src/img/country-flags/hn.png new file mode 100644 index 0000000..3585e21 Binary files /dev/null and b/assets/src/img/country-flags/hn.png differ diff --git a/assets/src/img/country-flags/hr.png b/assets/src/img/country-flags/hr.png new file mode 100644 index 0000000..ead3478 Binary files /dev/null and b/assets/src/img/country-flags/hr.png differ diff --git a/assets/src/img/country-flags/ht.png b/assets/src/img/country-flags/ht.png new file mode 100644 index 0000000..7185e7b Binary files /dev/null and b/assets/src/img/country-flags/ht.png differ diff --git a/assets/src/img/country-flags/hu.png b/assets/src/img/country-flags/hu.png new file mode 100644 index 0000000..278ad0e Binary files /dev/null and b/assets/src/img/country-flags/hu.png differ diff --git a/assets/src/img/country-flags/id.png b/assets/src/img/country-flags/id.png new file mode 100644 index 0000000..98c4e80 Binary files /dev/null and b/assets/src/img/country-flags/id.png differ diff --git a/assets/src/img/country-flags/ie.png b/assets/src/img/country-flags/ie.png new file mode 100644 index 0000000..f1b39d6 Binary files /dev/null and b/assets/src/img/country-flags/ie.png differ diff --git a/assets/src/img/country-flags/il.png b/assets/src/img/country-flags/il.png new file mode 100644 index 0000000..528fa57 Binary files /dev/null and b/assets/src/img/country-flags/il.png differ diff --git a/assets/src/img/country-flags/im.png b/assets/src/img/country-flags/im.png new file mode 100644 index 0000000..66267ed Binary files /dev/null and b/assets/src/img/country-flags/im.png differ diff --git a/assets/src/img/country-flags/in.png b/assets/src/img/country-flags/in.png new file mode 100644 index 0000000..c1ed48d Binary files /dev/null and b/assets/src/img/country-flags/in.png differ diff --git a/assets/src/img/country-flags/io.png b/assets/src/img/country-flags/io.png new file mode 100644 index 0000000..dceaa05 Binary files /dev/null and b/assets/src/img/country-flags/io.png differ diff --git a/assets/src/img/country-flags/iq.png b/assets/src/img/country-flags/iq.png new file mode 100644 index 0000000..f02ffb1 Binary files /dev/null and b/assets/src/img/country-flags/iq.png differ diff --git a/assets/src/img/country-flags/ir.png b/assets/src/img/country-flags/ir.png new file mode 100644 index 0000000..33e1859 Binary files /dev/null and b/assets/src/img/country-flags/ir.png differ diff --git a/assets/src/img/country-flags/is.png b/assets/src/img/country-flags/is.png new file mode 100644 index 0000000..0087aa0 Binary files /dev/null and b/assets/src/img/country-flags/is.png differ diff --git a/assets/src/img/country-flags/it.png b/assets/src/img/country-flags/it.png new file mode 100644 index 0000000..034fe15 Binary files /dev/null and b/assets/src/img/country-flags/it.png differ diff --git a/assets/src/img/country-flags/je.png b/assets/src/img/country-flags/je.png new file mode 100644 index 0000000..8f72065 Binary files /dev/null and b/assets/src/img/country-flags/je.png differ diff --git a/assets/src/img/country-flags/jm.png b/assets/src/img/country-flags/jm.png new file mode 100644 index 0000000..2b34a3f Binary files /dev/null and b/assets/src/img/country-flags/jm.png differ diff --git a/assets/src/img/country-flags/jo.png b/assets/src/img/country-flags/jo.png new file mode 100644 index 0000000..8f2bcf1 Binary files /dev/null and b/assets/src/img/country-flags/jo.png differ diff --git a/assets/src/img/country-flags/jp.png b/assets/src/img/country-flags/jp.png new file mode 100644 index 0000000..57247c5 Binary files /dev/null and b/assets/src/img/country-flags/jp.png differ diff --git a/assets/src/img/country-flags/ke.png b/assets/src/img/country-flags/ke.png new file mode 100644 index 0000000..3a39078 Binary files /dev/null and b/assets/src/img/country-flags/ke.png differ diff --git a/assets/src/img/country-flags/kg.png b/assets/src/img/country-flags/kg.png new file mode 100644 index 0000000..9240125 Binary files /dev/null and b/assets/src/img/country-flags/kg.png differ diff --git a/assets/src/img/country-flags/kh.png b/assets/src/img/country-flags/kh.png new file mode 100644 index 0000000..b18a879 Binary files /dev/null and b/assets/src/img/country-flags/kh.png differ diff --git a/assets/src/img/country-flags/ki.png b/assets/src/img/country-flags/ki.png new file mode 100644 index 0000000..87cb6cb Binary files /dev/null and b/assets/src/img/country-flags/ki.png differ diff --git a/assets/src/img/country-flags/km.png b/assets/src/img/country-flags/km.png new file mode 100644 index 0000000..69d2c7d Binary files /dev/null and b/assets/src/img/country-flags/km.png differ diff --git a/assets/src/img/country-flags/kn.png b/assets/src/img/country-flags/kn.png new file mode 100644 index 0000000..fd02a7c Binary files /dev/null and b/assets/src/img/country-flags/kn.png differ diff --git a/assets/src/img/country-flags/kp.png b/assets/src/img/country-flags/kp.png new file mode 100644 index 0000000..b7f07d8 Binary files /dev/null and b/assets/src/img/country-flags/kp.png differ diff --git a/assets/src/img/country-flags/kr.png b/assets/src/img/country-flags/kr.png new file mode 100644 index 0000000..4763499 Binary files /dev/null and b/assets/src/img/country-flags/kr.png differ diff --git a/assets/src/img/country-flags/kw.png b/assets/src/img/country-flags/kw.png new file mode 100644 index 0000000..5c3aa81 Binary files /dev/null and b/assets/src/img/country-flags/kw.png differ diff --git a/assets/src/img/country-flags/ky.png b/assets/src/img/country-flags/ky.png new file mode 100644 index 0000000..1c5017c Binary files /dev/null and b/assets/src/img/country-flags/ky.png differ diff --git a/assets/src/img/country-flags/kz.png b/assets/src/img/country-flags/kz.png new file mode 100644 index 0000000..3b3d356 Binary files /dev/null and b/assets/src/img/country-flags/kz.png differ diff --git a/assets/src/img/country-flags/la.png b/assets/src/img/country-flags/la.png new file mode 100644 index 0000000..64a94f5 Binary files /dev/null and b/assets/src/img/country-flags/la.png differ diff --git a/assets/src/img/country-flags/lb.png b/assets/src/img/country-flags/lb.png new file mode 100644 index 0000000..68a0376 Binary files /dev/null and b/assets/src/img/country-flags/lb.png differ diff --git a/assets/src/img/country-flags/lc.png b/assets/src/img/country-flags/lc.png new file mode 100644 index 0000000..fbeaad7 Binary files /dev/null and b/assets/src/img/country-flags/lc.png differ diff --git a/assets/src/img/country-flags/li.png b/assets/src/img/country-flags/li.png new file mode 100644 index 0000000..b46c952 Binary files /dev/null and b/assets/src/img/country-flags/li.png differ diff --git a/assets/src/img/country-flags/lk.png b/assets/src/img/country-flags/lk.png new file mode 100644 index 0000000..ae1f36a Binary files /dev/null and b/assets/src/img/country-flags/lk.png differ diff --git a/assets/src/img/country-flags/lr.png b/assets/src/img/country-flags/lr.png new file mode 100644 index 0000000..5736136 Binary files /dev/null and b/assets/src/img/country-flags/lr.png differ diff --git a/assets/src/img/country-flags/ls.png b/assets/src/img/country-flags/ls.png new file mode 100644 index 0000000..4ffb9fc Binary files /dev/null and b/assets/src/img/country-flags/ls.png differ diff --git a/assets/src/img/country-flags/lt.png b/assets/src/img/country-flags/lt.png new file mode 100644 index 0000000..2614dac Binary files /dev/null and b/assets/src/img/country-flags/lt.png differ diff --git a/assets/src/img/country-flags/lu.png b/assets/src/img/country-flags/lu.png new file mode 100644 index 0000000..71bb70c Binary files /dev/null and b/assets/src/img/country-flags/lu.png differ diff --git a/assets/src/img/country-flags/lv.png b/assets/src/img/country-flags/lv.png new file mode 100644 index 0000000..649c5ae Binary files /dev/null and b/assets/src/img/country-flags/lv.png differ diff --git a/assets/src/img/country-flags/ly.png b/assets/src/img/country-flags/ly.png new file mode 100644 index 0000000..e70aef9 Binary files /dev/null and b/assets/src/img/country-flags/ly.png differ diff --git a/assets/src/img/country-flags/ma.png b/assets/src/img/country-flags/ma.png new file mode 100644 index 0000000..b330c27 Binary files /dev/null and b/assets/src/img/country-flags/ma.png differ diff --git a/assets/src/img/country-flags/mc.png b/assets/src/img/country-flags/mc.png new file mode 100644 index 0000000..594ed85 Binary files /dev/null and b/assets/src/img/country-flags/mc.png differ diff --git a/assets/src/img/country-flags/md.png b/assets/src/img/country-flags/md.png new file mode 100644 index 0000000..82d4608 Binary files /dev/null and b/assets/src/img/country-flags/md.png differ diff --git a/assets/src/img/country-flags/me.png b/assets/src/img/country-flags/me.png new file mode 100644 index 0000000..f9d7f02 Binary files /dev/null and b/assets/src/img/country-flags/me.png differ diff --git a/assets/src/img/country-flags/mg.png b/assets/src/img/country-flags/mg.png new file mode 100644 index 0000000..d2c0f80 Binary files /dev/null and b/assets/src/img/country-flags/mg.png differ diff --git a/assets/src/img/country-flags/mh.png b/assets/src/img/country-flags/mh.png new file mode 100644 index 0000000..3d72763 Binary files /dev/null and b/assets/src/img/country-flags/mh.png differ diff --git a/assets/src/img/country-flags/mk.png b/assets/src/img/country-flags/mk.png new file mode 100644 index 0000000..f27d78f Binary files /dev/null and b/assets/src/img/country-flags/mk.png differ diff --git a/assets/src/img/country-flags/ml.png b/assets/src/img/country-flags/ml.png new file mode 100644 index 0000000..adc7d23 Binary files /dev/null and b/assets/src/img/country-flags/ml.png differ diff --git a/assets/src/img/country-flags/mm.png b/assets/src/img/country-flags/mm.png new file mode 100644 index 0000000..75c6369 Binary files /dev/null and b/assets/src/img/country-flags/mm.png differ diff --git a/assets/src/img/country-flags/mn.png b/assets/src/img/country-flags/mn.png new file mode 100644 index 0000000..7b2cc35 Binary files /dev/null and b/assets/src/img/country-flags/mn.png differ diff --git a/assets/src/img/country-flags/mo.png b/assets/src/img/country-flags/mo.png new file mode 100644 index 0000000..2565432 Binary files /dev/null and b/assets/src/img/country-flags/mo.png differ diff --git a/assets/src/img/country-flags/mp.png b/assets/src/img/country-flags/mp.png new file mode 100644 index 0000000..b1b27c0 Binary files /dev/null and b/assets/src/img/country-flags/mp.png differ diff --git a/assets/src/img/country-flags/mq.png b/assets/src/img/country-flags/mq.png new file mode 100644 index 0000000..b7525c1 Binary files /dev/null and b/assets/src/img/country-flags/mq.png differ diff --git a/assets/src/img/country-flags/mr.png b/assets/src/img/country-flags/mr.png new file mode 100644 index 0000000..0f4586d Binary files /dev/null and b/assets/src/img/country-flags/mr.png differ diff --git a/assets/src/img/country-flags/ms.png b/assets/src/img/country-flags/ms.png new file mode 100644 index 0000000..2032c4b Binary files /dev/null and b/assets/src/img/country-flags/ms.png differ diff --git a/assets/src/img/country-flags/mt.png b/assets/src/img/country-flags/mt.png new file mode 100644 index 0000000..153224d Binary files /dev/null and b/assets/src/img/country-flags/mt.png differ diff --git a/assets/src/img/country-flags/mu.png b/assets/src/img/country-flags/mu.png new file mode 100644 index 0000000..8b76367 Binary files /dev/null and b/assets/src/img/country-flags/mu.png differ diff --git a/assets/src/img/country-flags/mv.png b/assets/src/img/country-flags/mv.png new file mode 100644 index 0000000..d8f2104 Binary files /dev/null and b/assets/src/img/country-flags/mv.png differ diff --git a/assets/src/img/country-flags/mw.png b/assets/src/img/country-flags/mw.png new file mode 100644 index 0000000..4f73882 Binary files /dev/null and b/assets/src/img/country-flags/mw.png differ diff --git a/assets/src/img/country-flags/mx.png b/assets/src/img/country-flags/mx.png new file mode 100644 index 0000000..bc897eb Binary files /dev/null and b/assets/src/img/country-flags/mx.png differ diff --git a/assets/src/img/country-flags/my.png b/assets/src/img/country-flags/my.png new file mode 100644 index 0000000..9aa8c6d Binary files /dev/null and b/assets/src/img/country-flags/my.png differ diff --git a/assets/src/img/country-flags/mz.png b/assets/src/img/country-flags/mz.png new file mode 100644 index 0000000..3f04bf2 Binary files /dev/null and b/assets/src/img/country-flags/mz.png differ diff --git a/assets/src/img/country-flags/na.png b/assets/src/img/country-flags/na.png new file mode 100644 index 0000000..54bab3a Binary files /dev/null and b/assets/src/img/country-flags/na.png differ diff --git a/assets/src/img/country-flags/nc.png b/assets/src/img/country-flags/nc.png new file mode 100644 index 0000000..880d184 Binary files /dev/null and b/assets/src/img/country-flags/nc.png differ diff --git a/assets/src/img/country-flags/ne.png b/assets/src/img/country-flags/ne.png new file mode 100644 index 0000000..c587f32 Binary files /dev/null and b/assets/src/img/country-flags/ne.png differ diff --git a/assets/src/img/country-flags/nf.png b/assets/src/img/country-flags/nf.png new file mode 100644 index 0000000..572fd01 Binary files /dev/null and b/assets/src/img/country-flags/nf.png differ diff --git a/assets/src/img/country-flags/ng.png b/assets/src/img/country-flags/ng.png new file mode 100644 index 0000000..21e4cd2 Binary files /dev/null and b/assets/src/img/country-flags/ng.png differ diff --git a/assets/src/img/country-flags/ni.png b/assets/src/img/country-flags/ni.png new file mode 100644 index 0000000..59d2ae6 Binary files /dev/null and b/assets/src/img/country-flags/ni.png differ diff --git a/assets/src/img/country-flags/nl.png b/assets/src/img/country-flags/nl.png new file mode 100644 index 0000000..74d1a6c Binary files /dev/null and b/assets/src/img/country-flags/nl.png differ diff --git a/assets/src/img/country-flags/no.png b/assets/src/img/country-flags/no.png new file mode 100644 index 0000000..1b91d5c Binary files /dev/null and b/assets/src/img/country-flags/no.png differ diff --git a/assets/src/img/country-flags/np.png b/assets/src/img/country-flags/np.png new file mode 100644 index 0000000..2439fd7 Binary files /dev/null and b/assets/src/img/country-flags/np.png differ diff --git a/assets/src/img/country-flags/nr.png b/assets/src/img/country-flags/nr.png new file mode 100644 index 0000000..6653027 Binary files /dev/null and b/assets/src/img/country-flags/nr.png differ diff --git a/assets/src/img/country-flags/nu.png b/assets/src/img/country-flags/nu.png new file mode 100644 index 0000000..2acd015 Binary files /dev/null and b/assets/src/img/country-flags/nu.png differ diff --git a/assets/src/img/country-flags/nz.png b/assets/src/img/country-flags/nz.png new file mode 100644 index 0000000..da3a9ce Binary files /dev/null and b/assets/src/img/country-flags/nz.png differ diff --git a/assets/src/img/country-flags/om.png b/assets/src/img/country-flags/om.png new file mode 100644 index 0000000..6d53eaf Binary files /dev/null and b/assets/src/img/country-flags/om.png differ diff --git a/assets/src/img/country-flags/pa.png b/assets/src/img/country-flags/pa.png new file mode 100644 index 0000000..7b0938d Binary files /dev/null and b/assets/src/img/country-flags/pa.png differ diff --git a/assets/src/img/country-flags/pe.png b/assets/src/img/country-flags/pe.png new file mode 100644 index 0000000..2579527 Binary files /dev/null and b/assets/src/img/country-flags/pe.png differ diff --git a/assets/src/img/country-flags/pf.png b/assets/src/img/country-flags/pf.png new file mode 100644 index 0000000..a83b224 Binary files /dev/null and b/assets/src/img/country-flags/pf.png differ diff --git a/assets/src/img/country-flags/pg.png b/assets/src/img/country-flags/pg.png new file mode 100644 index 0000000..722cee7 Binary files /dev/null and b/assets/src/img/country-flags/pg.png differ diff --git a/assets/src/img/country-flags/ph.png b/assets/src/img/country-flags/ph.png new file mode 100644 index 0000000..c2af43a Binary files /dev/null and b/assets/src/img/country-flags/ph.png differ diff --git a/assets/src/img/country-flags/pk.png b/assets/src/img/country-flags/pk.png new file mode 100644 index 0000000..b3c8911 Binary files /dev/null and b/assets/src/img/country-flags/pk.png differ diff --git a/assets/src/img/country-flags/pl.png b/assets/src/img/country-flags/pl.png new file mode 100644 index 0000000..d4db002 Binary files /dev/null and b/assets/src/img/country-flags/pl.png differ diff --git a/assets/src/img/country-flags/pn.png b/assets/src/img/country-flags/pn.png new file mode 100644 index 0000000..acc1e64 Binary files /dev/null and b/assets/src/img/country-flags/pn.png differ diff --git a/assets/src/img/country-flags/pr.png b/assets/src/img/country-flags/pr.png new file mode 100644 index 0000000..253f92a Binary files /dev/null and b/assets/src/img/country-flags/pr.png differ diff --git a/assets/src/img/country-flags/ps.png b/assets/src/img/country-flags/ps.png new file mode 100644 index 0000000..5efc6eb Binary files /dev/null and b/assets/src/img/country-flags/ps.png differ diff --git a/assets/src/img/country-flags/pt.png b/assets/src/img/country-flags/pt.png new file mode 100644 index 0000000..fcc0e60 Binary files /dev/null and b/assets/src/img/country-flags/pt.png differ diff --git a/assets/src/img/country-flags/pw.png b/assets/src/img/country-flags/pw.png new file mode 100644 index 0000000..df14cd8 Binary files /dev/null and b/assets/src/img/country-flags/pw.png differ diff --git a/assets/src/img/country-flags/py.png b/assets/src/img/country-flags/py.png new file mode 100644 index 0000000..43bd2d2 Binary files /dev/null and b/assets/src/img/country-flags/py.png differ diff --git a/assets/src/img/country-flags/qa.png b/assets/src/img/country-flags/qa.png new file mode 100644 index 0000000..661e936 Binary files /dev/null and b/assets/src/img/country-flags/qa.png differ diff --git a/assets/src/img/country-flags/re.png b/assets/src/img/country-flags/re.png new file mode 100644 index 0000000..b8e120b Binary files /dev/null and b/assets/src/img/country-flags/re.png differ diff --git a/assets/src/img/country-flags/ro.png b/assets/src/img/country-flags/ro.png new file mode 100644 index 0000000..f064c1e Binary files /dev/null and b/assets/src/img/country-flags/ro.png differ diff --git a/assets/src/img/country-flags/rs.png b/assets/src/img/country-flags/rs.png new file mode 100644 index 0000000..4cc2587 Binary files /dev/null and b/assets/src/img/country-flags/rs.png differ diff --git a/assets/src/img/country-flags/ru.png b/assets/src/img/country-flags/ru.png new file mode 100644 index 0000000..9bc3ce6 Binary files /dev/null and b/assets/src/img/country-flags/ru.png differ diff --git a/assets/src/img/country-flags/rw.png b/assets/src/img/country-flags/rw.png new file mode 100644 index 0000000..d76d519 Binary files /dev/null and b/assets/src/img/country-flags/rw.png differ diff --git a/assets/src/img/country-flags/sa.png b/assets/src/img/country-flags/sa.png new file mode 100644 index 0000000..7151fe2 Binary files /dev/null and b/assets/src/img/country-flags/sa.png differ diff --git a/assets/src/img/country-flags/sb.png b/assets/src/img/country-flags/sb.png new file mode 100644 index 0000000..22ff0c2 Binary files /dev/null and b/assets/src/img/country-flags/sb.png differ diff --git a/assets/src/img/country-flags/sc.png b/assets/src/img/country-flags/sc.png new file mode 100644 index 0000000..d9aae43 Binary files /dev/null and b/assets/src/img/country-flags/sc.png differ diff --git a/assets/src/img/country-flags/sd.png b/assets/src/img/country-flags/sd.png new file mode 100644 index 0000000..a79e1cb Binary files /dev/null and b/assets/src/img/country-flags/sd.png differ diff --git a/assets/src/img/country-flags/se.png b/assets/src/img/country-flags/se.png new file mode 100644 index 0000000..deb3df1 Binary files /dev/null and b/assets/src/img/country-flags/se.png differ diff --git a/assets/src/img/country-flags/sg.png b/assets/src/img/country-flags/sg.png new file mode 100644 index 0000000..9eaaff2 Binary files /dev/null and b/assets/src/img/country-flags/sg.png differ diff --git a/assets/src/img/country-flags/sh.png b/assets/src/img/country-flags/sh.png new file mode 100644 index 0000000..53fdf1b Binary files /dev/null and b/assets/src/img/country-flags/sh.png differ diff --git a/assets/src/img/country-flags/si.png b/assets/src/img/country-flags/si.png new file mode 100644 index 0000000..07abf09 Binary files /dev/null and b/assets/src/img/country-flags/si.png differ diff --git a/assets/src/img/country-flags/sk.png b/assets/src/img/country-flags/sk.png new file mode 100644 index 0000000..4741be0 Binary files /dev/null and b/assets/src/img/country-flags/sk.png differ diff --git a/assets/src/img/country-flags/sl.png b/assets/src/img/country-flags/sl.png new file mode 100644 index 0000000..684daeb Binary files /dev/null and b/assets/src/img/country-flags/sl.png differ diff --git a/assets/src/img/country-flags/sm.png b/assets/src/img/country-flags/sm.png new file mode 100644 index 0000000..a56c085 Binary files /dev/null and b/assets/src/img/country-flags/sm.png differ diff --git a/assets/src/img/country-flags/sn.png b/assets/src/img/country-flags/sn.png new file mode 100644 index 0000000..0234587 Binary files /dev/null and b/assets/src/img/country-flags/sn.png differ diff --git a/assets/src/img/country-flags/so.png b/assets/src/img/country-flags/so.png new file mode 100644 index 0000000..8330183 Binary files /dev/null and b/assets/src/img/country-flags/so.png differ diff --git a/assets/src/img/country-flags/sr.png b/assets/src/img/country-flags/sr.png new file mode 100644 index 0000000..e793251 Binary files /dev/null and b/assets/src/img/country-flags/sr.png differ diff --git a/assets/src/img/country-flags/ss.png b/assets/src/img/country-flags/ss.png new file mode 100644 index 0000000..78a6409 Binary files /dev/null and b/assets/src/img/country-flags/ss.png differ diff --git a/assets/src/img/country-flags/st.png b/assets/src/img/country-flags/st.png new file mode 100644 index 0000000..e4b292c Binary files /dev/null and b/assets/src/img/country-flags/st.png differ diff --git a/assets/src/img/country-flags/sv.png b/assets/src/img/country-flags/sv.png new file mode 100644 index 0000000..604e6d4 Binary files /dev/null and b/assets/src/img/country-flags/sv.png differ diff --git a/assets/src/img/country-flags/sx.png b/assets/src/img/country-flags/sx.png new file mode 100644 index 0000000..8b561c7 Binary files /dev/null and b/assets/src/img/country-flags/sx.png differ diff --git a/assets/src/img/country-flags/sy.png b/assets/src/img/country-flags/sy.png new file mode 100644 index 0000000..2ecd5a8 Binary files /dev/null and b/assets/src/img/country-flags/sy.png differ diff --git a/assets/src/img/country-flags/sz.png b/assets/src/img/country-flags/sz.png new file mode 100644 index 0000000..b091ceb Binary files /dev/null and b/assets/src/img/country-flags/sz.png differ diff --git a/assets/src/img/country-flags/tc.png b/assets/src/img/country-flags/tc.png new file mode 100644 index 0000000..2bd0f4c Binary files /dev/null and b/assets/src/img/country-flags/tc.png differ diff --git a/assets/src/img/country-flags/td.png b/assets/src/img/country-flags/td.png new file mode 100644 index 0000000..78771bf Binary files /dev/null and b/assets/src/img/country-flags/td.png differ diff --git a/assets/src/img/country-flags/tf.png b/assets/src/img/country-flags/tf.png new file mode 100644 index 0000000..1458929 Binary files /dev/null and b/assets/src/img/country-flags/tf.png differ diff --git a/assets/src/img/country-flags/tg.png b/assets/src/img/country-flags/tg.png new file mode 100644 index 0000000..b639225 Binary files /dev/null and b/assets/src/img/country-flags/tg.png differ diff --git a/assets/src/img/country-flags/th.png b/assets/src/img/country-flags/th.png new file mode 100644 index 0000000..b38e353 Binary files /dev/null and b/assets/src/img/country-flags/th.png differ diff --git a/assets/src/img/country-flags/tj.png b/assets/src/img/country-flags/tj.png new file mode 100644 index 0000000..0dca916 Binary files /dev/null and b/assets/src/img/country-flags/tj.png differ diff --git a/assets/src/img/country-flags/tk.png b/assets/src/img/country-flags/tk.png new file mode 100644 index 0000000..54fb320 Binary files /dev/null and b/assets/src/img/country-flags/tk.png differ diff --git a/assets/src/img/country-flags/tl.png b/assets/src/img/country-flags/tl.png new file mode 100644 index 0000000..87feb92 Binary files /dev/null and b/assets/src/img/country-flags/tl.png differ diff --git a/assets/src/img/country-flags/tm.png b/assets/src/img/country-flags/tm.png new file mode 100644 index 0000000..f6daee1 Binary files /dev/null and b/assets/src/img/country-flags/tm.png differ diff --git a/assets/src/img/country-flags/tn.png b/assets/src/img/country-flags/tn.png new file mode 100644 index 0000000..199cadc Binary files /dev/null and b/assets/src/img/country-flags/tn.png differ diff --git a/assets/src/img/country-flags/to.png b/assets/src/img/country-flags/to.png new file mode 100644 index 0000000..533181d Binary files /dev/null and b/assets/src/img/country-flags/to.png differ diff --git a/assets/src/img/country-flags/tr.png b/assets/src/img/country-flags/tr.png new file mode 100644 index 0000000..da7239b Binary files /dev/null and b/assets/src/img/country-flags/tr.png differ diff --git a/assets/src/img/country-flags/tt.png b/assets/src/img/country-flags/tt.png new file mode 100644 index 0000000..6aa844c Binary files /dev/null and b/assets/src/img/country-flags/tt.png differ diff --git a/assets/src/img/country-flags/tv.png b/assets/src/img/country-flags/tv.png new file mode 100644 index 0000000..c17b10e Binary files /dev/null and b/assets/src/img/country-flags/tv.png differ diff --git a/assets/src/img/country-flags/tw.png b/assets/src/img/country-flags/tw.png new file mode 100644 index 0000000..df5d0d8 Binary files /dev/null and b/assets/src/img/country-flags/tw.png differ diff --git a/assets/src/img/country-flags/tz.png b/assets/src/img/country-flags/tz.png new file mode 100644 index 0000000..95daf34 Binary files /dev/null and b/assets/src/img/country-flags/tz.png differ diff --git a/assets/src/img/country-flags/ua.png b/assets/src/img/country-flags/ua.png new file mode 100644 index 0000000..09e4890 Binary files /dev/null and b/assets/src/img/country-flags/ua.png differ diff --git a/assets/src/img/country-flags/ug.png b/assets/src/img/country-flags/ug.png new file mode 100644 index 0000000..4970d3d Binary files /dev/null and b/assets/src/img/country-flags/ug.png differ diff --git a/assets/src/img/country-flags/us.png b/assets/src/img/country-flags/us.png new file mode 100644 index 0000000..53c4ba1 Binary files /dev/null and b/assets/src/img/country-flags/us.png differ diff --git a/assets/src/img/country-flags/uy.png b/assets/src/img/country-flags/uy.png new file mode 100644 index 0000000..fdeee28 Binary files /dev/null and b/assets/src/img/country-flags/uy.png differ diff --git a/assets/src/img/country-flags/uz.png b/assets/src/img/country-flags/uz.png new file mode 100644 index 0000000..e9ab4eb Binary files /dev/null and b/assets/src/img/country-flags/uz.png differ diff --git a/assets/src/img/country-flags/va.png b/assets/src/img/country-flags/va.png new file mode 100644 index 0000000..32356ad Binary files /dev/null and b/assets/src/img/country-flags/va.png differ diff --git a/assets/src/img/country-flags/vc.png b/assets/src/img/country-flags/vc.png new file mode 100644 index 0000000..1b6b1f6 Binary files /dev/null and b/assets/src/img/country-flags/vc.png differ diff --git a/assets/src/img/country-flags/ve.png b/assets/src/img/country-flags/ve.png new file mode 100644 index 0000000..78a43da Binary files /dev/null and b/assets/src/img/country-flags/ve.png differ diff --git a/assets/src/img/country-flags/vg.png b/assets/src/img/country-flags/vg.png new file mode 100644 index 0000000..4a599de Binary files /dev/null and b/assets/src/img/country-flags/vg.png differ diff --git a/assets/src/img/country-flags/vi.png b/assets/src/img/country-flags/vi.png new file mode 100644 index 0000000..0d97f68 Binary files /dev/null and b/assets/src/img/country-flags/vi.png differ diff --git a/assets/src/img/country-flags/vn.png b/assets/src/img/country-flags/vn.png new file mode 100644 index 0000000..57a0848 Binary files /dev/null and b/assets/src/img/country-flags/vn.png differ diff --git a/assets/src/img/country-flags/vu.png b/assets/src/img/country-flags/vu.png new file mode 100644 index 0000000..8c40151 Binary files /dev/null and b/assets/src/img/country-flags/vu.png differ diff --git a/assets/src/img/country-flags/ws.png b/assets/src/img/country-flags/ws.png new file mode 100644 index 0000000..1c0cadd Binary files /dev/null and b/assets/src/img/country-flags/ws.png differ diff --git a/assets/src/img/country-flags/ye.png b/assets/src/img/country-flags/ye.png new file mode 100644 index 0000000..a9d71cf Binary files /dev/null and b/assets/src/img/country-flags/ye.png differ diff --git a/assets/src/img/country-flags/za.png b/assets/src/img/country-flags/za.png new file mode 100644 index 0000000..9d14f3e Binary files /dev/null and b/assets/src/img/country-flags/za.png differ diff --git a/assets/src/img/country-flags/zm.png b/assets/src/img/country-flags/zm.png new file mode 100644 index 0000000..103232f Binary files /dev/null and b/assets/src/img/country-flags/zm.png differ diff --git a/assets/src/img/country-flags/zw.png b/assets/src/img/country-flags/zw.png new file mode 100644 index 0000000..6a19b44 Binary files /dev/null and b/assets/src/img/country-flags/zw.png differ diff --git a/assets/src/img/screenshot.png b/assets/src/img/screenshot.png new file mode 100644 index 0000000..5b79b6c Binary files /dev/null and b/assets/src/img/screenshot.png differ diff --git a/assets/src/index.html b/assets/src/index.html new file mode 100644 index 0000000..deb91b5 --- /dev/null +++ b/assets/src/index.html @@ -0,0 +1,14 @@ + + + + Ana - open web analytics + + + +
+ + + + diff --git a/assets/js/components/CountWidget.js b/assets/src/js/components/CountWidget.js similarity index 100% rename from assets/js/components/CountWidget.js rename to assets/src/js/components/CountWidget.js diff --git a/assets/js/components/DatePicker.js b/assets/src/js/components/DatePicker.js similarity index 100% rename from assets/js/components/DatePicker.js rename to assets/src/js/components/DatePicker.js diff --git a/assets/js/components/Graph.js b/assets/src/js/components/Graph.js similarity index 100% rename from assets/js/components/Graph.js rename to assets/src/js/components/Graph.js diff --git a/assets/js/components/GraphWidget.js b/assets/src/js/components/GraphWidget.js similarity index 100% rename from assets/js/components/GraphWidget.js rename to assets/src/js/components/GraphWidget.js diff --git a/assets/js/components/HeaderBar.js b/assets/src/js/components/HeaderBar.js similarity index 100% rename from assets/js/components/HeaderBar.js rename to assets/src/js/components/HeaderBar.js diff --git a/assets/js/components/LoginForm.js b/assets/src/js/components/LoginForm.js similarity index 100% rename from assets/js/components/LoginForm.js rename to assets/src/js/components/LoginForm.js diff --git a/assets/js/components/LogoutButton.js b/assets/src/js/components/LogoutButton.js similarity index 100% rename from assets/js/components/LogoutButton.js rename to assets/src/js/components/LogoutButton.js diff --git a/assets/js/components/Notification.js b/assets/src/js/components/Notification.js similarity index 100% rename from assets/js/components/Notification.js rename to assets/src/js/components/Notification.js diff --git a/assets/js/components/Pageviews.js b/assets/src/js/components/Pageviews.js similarity index 100% rename from assets/js/components/Pageviews.js rename to assets/src/js/components/Pageviews.js diff --git a/assets/js/components/Realtime.js b/assets/src/js/components/Realtime.js similarity index 100% rename from assets/js/components/Realtime.js rename to assets/src/js/components/Realtime.js diff --git a/assets/js/components/Table.js b/assets/src/js/components/Table.js similarity index 100% rename from assets/js/components/Table.js rename to assets/src/js/components/Table.js diff --git a/assets/js/lib/client.js b/assets/src/js/lib/client.js similarity index 100% rename from assets/js/lib/client.js rename to assets/src/js/lib/client.js diff --git a/assets/js/lib/numbers.js b/assets/src/js/lib/numbers.js similarity index 100% rename from assets/js/lib/numbers.js rename to assets/src/js/lib/numbers.js diff --git a/assets/js/pages/dashboard.js b/assets/src/js/pages/dashboard.js similarity index 100% rename from assets/js/pages/dashboard.js rename to assets/src/js/pages/dashboard.js diff --git a/assets/js/pages/login.js b/assets/src/js/pages/login.js similarity index 100% rename from assets/js/pages/login.js rename to assets/src/js/pages/login.js diff --git a/assets/js/script.js b/assets/src/js/script.js similarity index 100% rename from assets/js/script.js rename to assets/src/js/script.js diff --git a/assets/src/js/tracker.js b/assets/src/js/tracker.js new file mode 100644 index 0000000..2eb4da6 --- /dev/null +++ b/assets/src/js/tracker.js @@ -0,0 +1,69 @@ +'use strict'; + +var queue = window.ana.q || []; +var trackerUrl = '//ana.dev/collect'; +var commands = { + "trackPageview": trackPageview, + "setTrackerUrl": setTrackerUrl, +}; + +// convert object to query string +function stringifyObject(json) { + var keys = Object.keys(json); + + // omit empty + keys = keys.filter(function(k) { + return json[k].length > 0; + }); + + return '?' + + keys.map(function(k) { + return encodeURIComponent(k) + '=' + + encodeURIComponent(json[k]); + }).join('&'); +} + +function setTrackerUrl(v) { + trackerUrl = v; +} + +function trackPageview() { + // Respect "Do Not Track" requests + if( navigator.DonotTrack == 1 ) { + return; + } + + // get the path or canonical + var path = location.pathname + location.search; + var canonical = document.querySelector('link[rel="canonical"]'); + if(canonical && canonical.href) { + path = canonical.href.substring(canonical.href.indexOf('/', 7)) || '/'; + } + + var d = { + h: location.hostname, + t: document.title, + l: navigator.language, + p: path, + sr: screen.width + "x" + screen.height, + t: document.title, + ru: document.referrer, + rk: "" + }; + + var i = document.createElement('img'); + i.src = trackerUrl + stringifyObject(d); + document.body.appendChild(i); +} + +// override global ana object +window.ana = function() { + var args = [].slice.call(arguments); + var c = args.shift(); + commands[c].apply(this, args); +}; + +// process existing queue +queue.forEach(function(i) { + ana.apply(this, i); +}); diff --git a/assets/sass/_forms.scss b/assets/src/sass/_forms.scss similarity index 100% rename from assets/sass/_forms.scss rename to assets/src/sass/_forms.scss diff --git a/assets/sass/_graphs.scss b/assets/src/sass/_graphs.scss similarity index 100% rename from assets/sass/_graphs.scss rename to assets/src/sass/_graphs.scss diff --git a/assets/sass/_grid.scss b/assets/src/sass/_grid.scss similarity index 100% rename from assets/sass/_grid.scss rename to assets/src/sass/_grid.scss diff --git a/assets/sass/_normalize.scss b/assets/src/sass/_normalize.scss similarity index 100% rename from assets/sass/_normalize.scss rename to assets/src/sass/_normalize.scss diff --git a/assets/sass/_tables.scss b/assets/src/sass/_tables.scss similarity index 100% rename from assets/sass/_tables.scss rename to assets/src/sass/_tables.scss diff --git a/assets/sass/_util.scss b/assets/src/sass/_util.scss similarity index 100% rename from assets/sass/_util.scss rename to assets/src/sass/_util.scss diff --git a/assets/sass/styles.scss b/assets/src/sass/styles.scss similarity index 100% rename from assets/sass/styles.scss rename to assets/src/sass/styles.scss diff --git a/gulpfile.js b/gulpfile.js index 9979ed7..5f6abdd 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -12,7 +12,7 @@ const uglify = require('gulp-uglify') const pump = require('pump') const debug = process.env.NODE_ENV !== 'production'; -let defaultTasks = [ 'browserify', 'sass', 'tracker' ] ; +let defaultTasks = [ 'browserify', 'sass', 'tracker', 'html', 'img' ] ; if( ! debug ) { defaultTasks.push( 'minify' ); } @@ -21,7 +21,7 @@ gulp.task('default', defaultTasks); gulp.task('browserify', function () { return browserify({ - entries: './assets/js/script.js', + entries: './assets/src/js/script.js', debug: debug }) .transform("babelify", {presets: ["es2015"]}) @@ -32,40 +32,44 @@ gulp.task('browserify', function () { }) .pipe(source('script.js')) .pipe(buffer()) - .pipe(gulp.dest('./static/js/')) + .pipe(gulp.dest('./assets/dist/js/')) }); gulp.task('minify', function(cb) { process.env.NODE_ENV = 'production'; pump([ - gulp.src('./static/js/*.js'), + gulp.src('./assets/dist/js/*.js'), uglify().on('error', gutil.log), - gulp.dest('./static/js/') + gulp.dest('./assets/dist/js/') ], cb) }); gulp.task('img', function() { - return gulp.src('./assets/img/**/*') - .pipe(gulp.dest('./static/img')) + return gulp.src('./assets/src/img/**/*') + .pipe(gulp.dest('./assets/dist/img')) }); +gulp.task('html', function() { + return gulp.src('./assets/src/**/*.html') + .pipe(gulp.dest('./assets/dist')) +}); gulp.task('tracker', function() { - return gulp.src('./assets/js/tracker.js') - .pipe(gulp.dest('./static/js')) + return gulp.src('./assets/src/js/tracker.js') + .pipe(gulp.dest('./assets/dist/js')) }); gulp.task('sass', function () { - var files = './assets/sass/[^_]*.scss'; + var files = './assets/src/sass/[^_]*.scss'; return gulp.src(files) .pipe(sass()) .on('error', gutil.log) .pipe(rename({ extname: '.css' })) - .pipe(gulp.dest('./static/css')) + .pipe(gulp.dest('./assets/dist/css')) }); gulp.task('watch', ['default'], function() { - gulp.watch(['./assets/js/**/*.js'], ['browserify', 'tracker'] ); - gulp.watch(['./assets/sass/**/**/*.scss'], ['sass'] ); + gulp.watch(['./assets/src/js/**/*.js'], ['browserify', 'tracker'] ); + gulp.watch(['./assets/src/sass/**/**/*.scss'], ['sass'] ); }); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5573cfc --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5924 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "JSONStream": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", + "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "dev": true, + "requires": { + "jsonparse": "1.3.1", + "through": "2.3.8" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + }, + "acorn-node": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.3.0.tgz", + "integrity": "sha512-efP54n3d1aLfjL2UMdaXa6DsswwzJeI5rqhbFvXMrKiJ6eJFpf+7R0zN7t8IC+XKn2YOAFAv6xbBNgHUkoHWLw==", + "dev": true, + "requires": { + "acorn": "5.5.3", + "xtend": "4.0.1" + }, + "dependencies": { + "acorn": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-filter": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", + "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-map": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", + "integrity": "sha1-iKK6tz0c97zVwbEYoAP2b2ZfpmI=", + "dev": true + }, + "array-reduce": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/array-reduce/-/array-reduce-0.0.0.tgz", + "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "astw": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/astw/-/astw-2.2.0.tgz", + "integrity": "sha1-e9QXhNMkk5h66yOba04cV6hzuRc=", + "dev": true, + "requires": { + "acorn": "4.0.13" + } + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.0.tgz", + "integrity": "sha512-SuiKH8vbsOyCALjA/+EINmt/Kdl+TQPrtFgW7XZZcwtryFu9e5kQoX3bjCW6mIvGH1fbeAZZuvwGR5IlBRznGw==", + "dev": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.1", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.5", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.5", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + } + } + }, + "babel-helper-builder-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "esutils": "2.0.2" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.5" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "6.26.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.5", + "home-or-tmp": "2.0.0", + "lodash": "4.17.5", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.5", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.5" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.4", + "lodash": "4.17.5" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.5", + "to-fast-properties": "1.0.3" + } + }, + "babelify": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "object-assign": "4.1.1" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "base64-js": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", + "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "dev": true, + "requires": { + "readable-stream": "2.3.6", + "safe-buffer": "5.1.1" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-pack": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz", + "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "combine-source-map": "0.8.0", + "defined": "1.0.0", + "safe-buffer": "5.1.1", + "through2": "2.0.3", + "umd": "3.0.3" + } + }, + "browser-resolve": { + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz", + "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=", + "dev": true, + "requires": { + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", + "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", + "dev": true + } + } + }, + "browserify": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-13.3.0.tgz", + "integrity": "sha1-tanJAgJD8McORnW+yCI7xifkFc4=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "assert": "1.4.1", + "browser-pack": "6.1.0", + "browser-resolve": "1.11.2", + "browserify-zlib": "0.1.4", + "buffer": "4.9.1", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "defined": "1.0.0", + "deps-sort": "2.0.0", + "domain-browser": "1.1.7", + "duplexer2": "0.1.4", + "events": "1.1.1", + "glob": "7.1.2", + "has": "1.0.1", + "htmlescape": "1.1.1", + "https-browserify": "0.0.1", + "inherits": "2.0.3", + "insert-module-globals": "7.0.6", + "labeled-stream-splicer": "2.0.1", + "module-deps": "4.1.1", + "os-browserify": "0.1.2", + "parents": "1.0.1", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "read-only-stream": "2.0.0", + "readable-stream": "2.3.6", + "resolve": "1.7.1", + "shasum": "1.0.2", + "shell-quote": "1.6.1", + "stream-browserify": "2.0.1", + "stream-http": "2.8.1", + "string_decoder": "0.10.31", + "subarg": "1.0.0", + "syntax-error": "1.4.0", + "through2": "2.0.3", + "timers-browserify": "1.4.2", + "tty-browserify": "0.0.1", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4", + "xtend": "4.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "1.2.0", + "browserify-des": "1.0.1", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.1.tgz", + "integrity": "sha512-zy0Cobe3hhgpiOM32Tj7KQ3Vl91m0njwsjzZQK1L+JDf11dzP9qIvjreVinsvXrgfjhStXwUWAEpB9D7Gwmayw==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.1" + } + }, + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", + "dev": true, + "requires": { + "pako": "0.2.9" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.3.0", + "ieee754": "1.1.11", + "isarray": "1.0.0" + } + }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "cached-path-relative": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.0.1.tgz", + "integrity": "sha1-0JxLUoAKpMB44t2BqGmqyQ0uVOc=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "combine-source-map": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz", + "integrity": "sha1-pY0N8ELBhvz4IqjoAV9UUNLXmos=", + "dev": true, + "requires": { + "convert-source-map": "1.1.3", + "inline-source-map": "0.6.2", + "lodash.memoize": "3.0.4", + "source-map": "0.5.7" + }, + "dependencies": { + "convert-source-map": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz", + "integrity": "sha1-SCnId+n+SbMWHzvzZziI4gRpmGA=", + "dev": true + } + } + }, + "combined-stream": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.0.6", + "typedarray": "0.0.6" + }, + "dependencies": { + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", + "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-ecdh": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.1.tgz", + "integrity": "sha512-iZvCCg8XqHQZ1ioNBTzXS/cQSkqkqcPs8xSX4upNB+DAk9Ht3uzQf2J32uAHNCne8LDmKr29AgZrEs4oIrwLuQ==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "md5.js": "1.3.4", + "ripemd160": "2.0.2", + "sha.js": "2.4.11" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.2.0", + "inherits": "2.0.3", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.1", + "sha.js": "2.4.11" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "4.1.2", + "which": "1.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", + "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + } + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.1", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.1", + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "diffie-hellman": "5.0.3", + "inherits": "2.0.3", + "pbkdf2": "3.0.16", + "public-encrypt": "4.0.2", + "randombytes": "2.0.6", + "randomfill": "1.0.4" + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "d3": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz", + "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==", + "requires": { + "d3-array": "1.2.1", + "d3-axis": "1.0.8", + "d3-brush": "1.0.4", + "d3-chord": "1.0.4", + "d3-collection": "1.0.4", + "d3-color": "1.0.3", + "d3-dispatch": "1.0.3", + "d3-drag": "1.2.1", + "d3-dsv": "1.0.8", + "d3-ease": "1.0.3", + "d3-force": "1.1.0", + "d3-format": "1.2.2", + "d3-geo": "1.9.1", + "d3-hierarchy": "1.1.5", + "d3-interpolate": "1.1.6", + "d3-path": "1.0.5", + "d3-polygon": "1.0.3", + "d3-quadtree": "1.0.3", + "d3-queue": "3.0.7", + "d3-random": "1.1.0", + "d3-request": "1.0.6", + "d3-scale": "1.0.7", + "d3-selection": "1.3.0", + "d3-shape": "1.2.0", + "d3-time": "1.0.8", + "d3-time-format": "2.1.1", + "d3-timer": "1.0.7", + "d3-transition": "1.1.1", + "d3-voronoi": "1.1.2", + "d3-zoom": "1.7.1" + } + }, + "d3-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", + "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==" + }, + "d3-axis": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz", + "integrity": "sha1-MacFoLU15ldZ3hQXOjGTMTfxjvo=" + }, + "d3-brush": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz", + "integrity": "sha1-AMLyOAGfJPbAoZSibUGhUw/+e8Q=", + "requires": { + "d3-dispatch": "1.0.3", + "d3-drag": "1.2.1", + "d3-interpolate": "1.1.6", + "d3-selection": "1.3.0", + "d3-transition": "1.1.1" + } + }, + "d3-chord": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz", + "integrity": "sha1-fexPC6iG9xP+ERxF92NBT290yiw=", + "requires": { + "d3-array": "1.2.1", + "d3-path": "1.0.5" + } + }, + "d3-collection": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", + "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI=" + }, + "d3-color": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", + "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=" + }, + "d3-dispatch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", + "integrity": "sha1-RuFJHqqbWMNY/OW+TovtYm54cfg=" + }, + "d3-drag": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz", + "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==", + "requires": { + "d3-dispatch": "1.0.3", + "d3-selection": "1.3.0" + } + }, + "d3-dsv": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz", + "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==", + "requires": { + "commander": "2.15.1", + "iconv-lite": "0.4.21", + "rw": "1.3.3" + } + }, + "d3-ease": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz", + "integrity": "sha1-aL+8NJM4o4DETYrMT7wzBKotjA4=" + }, + "d3-force": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", + "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", + "requires": { + "d3-collection": "1.0.4", + "d3-dispatch": "1.0.3", + "d3-quadtree": "1.0.3", + "d3-timer": "1.0.7" + } + }, + "d3-format": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz", + "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==" + }, + "d3-geo": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz", + "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==", + "requires": { + "d3-array": "1.2.1" + } + }, + "d3-hierarchy": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz", + "integrity": "sha1-ochFxC+Eoga88cAcAQmOpN2qeiY=" + }, + "d3-interpolate": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", + "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", + "requires": { + "d3-color": "1.0.3" + } + }, + "d3-path": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz", + "integrity": "sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q=" + }, + "d3-polygon": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz", + "integrity": "sha1-FoiOkCZGCTPysXllKtN4Ik04LGI=" + }, + "d3-quadtree": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", + "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg=" + }, + "d3-queue": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz", + "integrity": "sha1-yTouVLQXwJWRKdfXP2z31Ckudhg=" + }, + "d3-random": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz", + "integrity": "sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM=" + }, + "d3-request": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz", + "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==", + "requires": { + "d3-collection": "1.0.4", + "d3-dispatch": "1.0.3", + "d3-dsv": "1.0.8", + "xmlhttprequest": "1.8.0" + } + }, + "d3-scale": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", + "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", + "requires": { + "d3-array": "1.2.1", + "d3-collection": "1.0.4", + "d3-color": "1.0.3", + "d3-format": "1.2.2", + "d3-interpolate": "1.1.6", + "d3-time": "1.0.8", + "d3-time-format": "2.1.1" + } + }, + "d3-selection": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz", + "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==" + }, + "d3-shape": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz", + "integrity": "sha1-RdAVOPBkuv0F6j1tLLdI/YxB93c=", + "requires": { + "d3-path": "1.0.5" + } + }, + "d3-time": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz", + "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ==" + }, + "d3-time-format": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz", + "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==", + "requires": { + "d3-time": "1.0.8" + } + }, + "d3-timer": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", + "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==" + }, + "d3-tip": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.7.1.tgz", + "integrity": "sha1-eMv1VPZ7cgpw47DxkeFM/+aM3Xk=", + "requires": { + "d3": "4.13.0" + } + }, + "d3-transition": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz", + "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==", + "requires": { + "d3-color": "1.0.3", + "d3-dispatch": "1.0.3", + "d3-ease": "1.0.3", + "d3-interpolate": "1.1.6", + "d3-selection": "1.3.0", + "d3-timer": "1.0.7" + } + }, + "d3-voronoi": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", + "integrity": "sha1-Fodmfo8TotFYyAwUgMWinLDYlzw=" + }, + "d3-zoom": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz", + "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==", + "requires": { + "d3-dispatch": "1.0.3", + "d3-drag": "1.2.1", + "d3-interpolate": "1.1.6", + "d3-selection": "1.3.0", + "d3-transition": "1.1.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.4" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "deps-sort": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.0.tgz", + "integrity": "sha1-CRckkC6EZYJg65EHSMzNGvbiH7U=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "shasum": "1.0.2", + "subarg": "1.0.0", + "through2": "2.0.3" + } + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "detective": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz", + "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==", + "dev": true, + "requires": { + "acorn": "5.5.3", + "defined": "1.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "dev": true + } + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "domain-browser": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz", + "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "requires": { + "once": "1.4.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.3" + } + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "gulp-rename": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", + "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", + "dev": true + }, + "gulp-sass": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-2.3.2.tgz", + "integrity": "sha1-grerkP6QLNw0wE8YDZLyw0kC3VI=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash.clonedeep": "4.5.0", + "node-sass": "3.13.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-uglify": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-2.1.2.tgz", + "integrity": "sha1-bbhbHQ7mPRgFhZK2WGSdZcLsRUE=", + "requires": { + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash": "4.17.5", + "make-error-cause": "1.2.2", + "through2": "2.0.3", + "uglify-js": "2.8.29", + "uglify-save-license": "0.4.1", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "requires": { + "glogg": "1.0.1" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.5.2", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "requires": { + "sparkles": "1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "dev": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", + "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "dev": true + }, + "htmlescape": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz", + "integrity": "sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E=", + "dev": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" + } + }, + "https-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz", + "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", + "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", + "requires": { + "safer-buffer": "2.1.2" + } + }, + "ieee754": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.11.tgz", + "integrity": "sha512-VhDzCKN7K8ufStx/CLj5/PDTMgph+qwN5Pkd5i0sGnVwk56zJ0lkT8Qzi1xqWLS0Wp29DgDtNeS7v8/wMoZeHg==", + "dev": true + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inline-source-map": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz", + "integrity": "sha1-+Tk0ccGKedFyT4Y/o4tYY3Ct4qU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "insert-module-globals": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.0.6.tgz", + "integrity": "sha512-R3sidKJr3SsggqQQ5cEwQb3pWG8RNx0UnpyeiOSR6jorRIeAOzH2gkTWnNdMnyRiVbjrG047K7UCtlMkQ1Mo9w==", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "combine-source-map": "0.8.0", + "concat-stream": "1.6.2", + "is-buffer": "1.1.6", + "lexical-scope": "1.2.0", + "path-is-absolute": "1.0.1", + "process": "0.11.10", + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "1.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "typedarray": "0.0.6" + } + } + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "1.0.0", + "is-windows": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-odd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", + "dev": true, + "requires": { + "is-number": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-base64": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz", + "integrity": "sha1-YRwj6BTbN1Un34URk9tZ3Sryf0U=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.6" + } + }, + "labeled-stream-splicer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", + "integrity": "sha512-MC94mHZRvJ3LfykJlTUipBqenZz1pacOZEMhhQ8dMGcDHs0SBE5GbsavUXV7YtP3icBW17W0Zy1I0lfASmo9Pg==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "isarray": "2.0.4", + "stream-splicer": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.4.tgz", + "integrity": "sha512-GMxXOiUirWg1xTKRipM0Ek07rX+ubx4nNVElTJdNLYmNO/2YrDkgJGw9CljXn+r4EWiDQg/8lsRdHyg2PJuUaA==", + "dev": true + } + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "lexical-scope": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/lexical-scope/-/lexical-scope-1.2.0.tgz", + "integrity": "sha1-/Ope3HBKSzqHls3KQZw6CvryLfQ=", + "dev": true, + "requires": { + "astw": "2.2.0" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.7.1" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "lodash": { + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.memoize": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz", + "integrity": "sha1-LcvSwofLwKVcxCMovQxzYVDVPj8=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "make-error": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", + "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==" + }, + "make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha1-3wOI/NCzeBbf8KX7gQiTl3fcvJ0=", + "requires": { + "make-error": "1.3.4" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "1.33.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "module-deps": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-4.1.1.tgz", + "integrity": "sha1-IyFYM/HaE/1gbMuAh7RIUty4If0=", + "dev": true, + "requires": { + "JSONStream": "1.3.2", + "browser-resolve": "1.11.2", + "cached-path-relative": "1.0.1", + "concat-stream": "1.5.2", + "defined": "1.0.0", + "detective": "4.7.1", + "duplexer2": "0.1.4", + "inherits": "2.0.3", + "parents": "1.0.1", + "readable-stream": "2.3.6", + "resolve": "1.7.1", + "stream-combiner2": "1.1.1", + "subarg": "1.0.0", + "through2": "2.0.3", + "xtend": "4.0.1" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true + }, + "nanomatch": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "natives": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.3.tgz", + "integrity": "sha512-BZGSYV4YOLxzoTK73l0/s/0sH9l8SHs2ocReMH1f8JYSh5FUWu4ZrKCpJdRkWXV6HFR/pZDz7bwWOVAY07q77g==", + "dev": true + }, + "node-gyp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", + "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", + "dev": true, + "requires": { + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.85.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "node-sass": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-3.13.1.tgz", + "integrity": "sha1-ckD7v/I5YwS0IjUn7TAgWJwAT8I=", + "dev": true, + "requires": { + "async-foreach": "0.1.3", + "chalk": "1.1.3", + "cross-spawn": "3.0.1", + "gaze": "1.1.2", + "get-stdin": "4.0.1", + "glob": "7.1.2", + "in-publish": "2.0.0", + "lodash.assign": "4.2.0", + "lodash.clonedeep": "4.5.0", + "meow": "3.7.0", + "mkdirp": "0.5.1", + "nan": "2.10.0", + "node-gyp": "3.6.2", + "npmlog": "4.1.2", + "request": "2.85.0", + "sass-graph": "2.2.4" + }, + "dependencies": { + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "dev": true, + "requires": { + "globule": "1.2.0" + } + }, + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.5", + "minimatch": "3.0.4" + } + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.1" + }, + "dependencies": { + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-browserify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", + "integrity": "sha1-ScoCk+CxlZCl9d4Qx/JlphfY/lQ=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", + "dev": true + }, + "parents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz", + "integrity": "sha1-/t1NK/GTp3dF/nHjcdc8MwfZx1E=", + "dev": true, + "requires": { + "path-platform": "0.11.15" + } + }, + "parse-asn1": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz", + "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", + "dev": true, + "requires": { + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-platform": { + "version": "0.11.15", + "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz", + "integrity": "sha1-6GQhf3TDaFDwhSt43Hv31KVyG/I=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.16.tgz", + "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", + "dev": true, + "requires": { + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.1", + "sha.js": "2.4.11" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "preact": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-6.4.0.tgz", + "integrity": "sha1-G4yZdUsAJjmhwz5oF17vqYoBzBQ=" + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.2.tgz", + "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" + } + }, + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, + "read-only-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", + "integrity": "sha1-JyT9aoET1zdkrCiNQ4YnDB2/F/A=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.7.1" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "resolve": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + } + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.5", + "scss-tokenizer": "0.2.3", + "yargs": "7.1.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" + } + } + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "2.4.3", + "source-map": "0.4.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shasum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz", + "integrity": "sha1-5wEjENj0F/TetXEhUOVni4euVl8=", + "dev": true, + "requires": { + "json-stable-stringify": "0.0.1", + "sha.js": "2.4.11" + } + }, + "shell-quote": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.6.1.tgz", + "integrity": "sha1-9HgZSczkAmlxJ0MOo7PFR29IF2c=", + "dev": true, + "requires": { + "array-filter": "0.0.1", + "array-map": "0.0.0", + "array-reduce": "0.0.0", + "jsonify": "0.0.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "dev": true, + "requires": { + "hoek": "4.2.1" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "2.1.0", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=" + }, + "spdx-correct": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", + "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", + "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", + "integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "sshpk": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.6" + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "dev": true + }, + "stream-http": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz", + "integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "stream-splicer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.0.tgz", + "integrity": "sha1-G2O+Q4oTPktnHMGTUZdgAXWRDYM=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.6" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "subarg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", + "integrity": "sha1-9izxdYHplrSPyWVpn1TAauJouNI=", + "dev": true, + "requires": { + "minimist": "1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "syntax-error": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz", + "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==", + "dev": true, + "requires": { + "acorn-node": "1.3.0" + } + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timers-browserify": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz", + "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=", + "dev": true, + "requires": { + "process": "0.11.10" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, + "tough-cookie": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=" + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "optional": true + }, + "umd": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz", + "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "use": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", + "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", + "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", + "dev": true, + "requires": { + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-buffer/-/vinyl-buffer-1.0.1.tgz", + "integrity": "sha1-lsGjR5uMU5JULGEgKQE7Wyf4i78=", + "dev": true, + "requires": { + "bl": "1.2.2", + "through2": "2.0.3" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vinyl-source-stream": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz", + "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=", + "dev": true, + "requires": { + "through2": "2.0.3", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "requires": { + "source-map": "0.5.7" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } + } + } +} diff --git a/api/api.go b/pkg/api/api.go similarity index 100% rename from api/api.go rename to pkg/api/api.go diff --git a/api/api_test.go b/pkg/api/api_test.go similarity index 100% rename from api/api_test.go rename to pkg/api/api_test.go diff --git a/api/auth.go b/pkg/api/auth.go similarity index 97% rename from api/auth.go rename to pkg/api/auth.go index d3ae561..c564003 100644 --- a/api/auth.go +++ b/pkg/api/auth.go @@ -6,7 +6,7 @@ import ( "net/http" "os" - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/datastore" "github.com/gorilla/sessions" "golang.org/x/crypto/bcrypt" ) diff --git a/api/browsers.go b/pkg/api/browsers.go similarity index 87% rename from api/browsers.go rename to pkg/api/browsers.go index 8912217..0e6c861 100644 --- a/api/browsers.go +++ b/pkg/api/browsers.go @@ -1,7 +1,7 @@ package api import ( - "github.com/dannyvankooten/ana/count" + "github.com/dannyvankooten/ana/pkg/count" "net/http" ) diff --git a/api/collect.go b/pkg/api/collect.go similarity index 97% rename from api/collect.go rename to pkg/api/collect.go index b412243..672631d 100644 --- a/api/collect.go +++ b/pkg/api/collect.go @@ -8,8 +8,8 @@ import ( "strings" "time" - "github.com/dannyvankooten/ana/datastore" - "github.com/dannyvankooten/ana/models" + "github.com/dannyvankooten/ana/pkg/datastore" + "github.com/dannyvankooten/ana/pkg/models" "github.com/mssola/user_agent" ) diff --git a/api/languages.go b/pkg/api/languages.go similarity index 87% rename from api/languages.go rename to pkg/api/languages.go index 625fb76..399cd57 100644 --- a/api/languages.go +++ b/pkg/api/languages.go @@ -3,7 +3,7 @@ package api import ( "net/http" - "github.com/dannyvankooten/ana/count" + "github.com/dannyvankooten/ana/pkg/count" ) // URL: /api/languages diff --git a/api/pageviews.go b/pkg/api/pageviews.go similarity index 94% rename from api/pageviews.go rename to pkg/api/pageviews.go index 9756040..a7f2389 100644 --- a/api/pageviews.go +++ b/pkg/api/pageviews.go @@ -3,8 +3,8 @@ package api import ( "net/http" - "github.com/dannyvankooten/ana/count" - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/count" + "github.com/dannyvankooten/ana/pkg/datastore" ) type pageviews struct { diff --git a/api/referrers.go b/pkg/api/referrers.go similarity index 87% rename from api/referrers.go rename to pkg/api/referrers.go index a10015a..43d9d29 100644 --- a/api/referrers.go +++ b/pkg/api/referrers.go @@ -3,7 +3,7 @@ package api import ( "net/http" - "github.com/dannyvankooten/ana/count" + "github.com/dannyvankooten/ana/pkg/count" ) // URL: /api/referrers diff --git a/api/screens.go b/pkg/api/screens.go similarity index 87% rename from api/screens.go rename to pkg/api/screens.go index 764f3a1..1cff344 100644 --- a/api/screens.go +++ b/pkg/api/screens.go @@ -3,7 +3,7 @@ package api import ( "net/http" - "github.com/dannyvankooten/ana/count" + "github.com/dannyvankooten/ana/pkg/count" ) // URL: /api/screen-resolutions diff --git a/api/visitors.go b/pkg/api/visitors.go similarity index 94% rename from api/visitors.go rename to pkg/api/visitors.go index d986443..7325425 100644 --- a/api/visitors.go +++ b/pkg/api/visitors.go @@ -3,7 +3,7 @@ package api import ( "net/http" - "github.com/dannyvankooten/ana/count" + "github.com/dannyvankooten/ana/pkg/count" ) // URL: /api/visitors/count diff --git a/commands/data.go b/pkg/commands/data.go similarity index 72% rename from commands/data.go rename to pkg/commands/data.go index 1c08519..eee9d20 100644 --- a/commands/data.go +++ b/pkg/commands/data.go @@ -1,8 +1,8 @@ package commands import ( - "github.com/dannyvankooten/ana/count" - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/count" + "github.com/dannyvankooten/ana/pkg/datastore" ) // Seed creates n database records with dummy data diff --git a/commands/server.go b/pkg/commands/server.go similarity index 82% rename from commands/server.go rename to pkg/commands/server.go index 1abf88d..c19f36e 100644 --- a/commands/server.go +++ b/pkg/commands/server.go @@ -2,7 +2,7 @@ package commands import ( "fmt" - "github.com/dannyvankooten/ana/api" + "github.com/dannyvankooten/ana/pkg/api" "github.com/gorilla/handlers" "github.com/gorilla/mux" "log" @@ -30,11 +30,11 @@ func Server(port int) { //r.Handle("/api/countries", api.Authorize(api.GetCountriesHandler)).Methods("GET") r.Handle("/api/browsers", api.Authorize(api.GetBrowsersHandler)).Methods("GET") - r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/")))) - r.Path("/tracker.js").Handler(http.FileServer(http.Dir("./static/js/"))) - r.Handle("/", http.FileServer(http.Dir("./views/"))) + r.Path("/tracker.js").Handler(http.FileServer(http.Dir("./assets/dist/js/"))) - log.Printf("HTTP server will now start listening on :%d\n", port) + r.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(http.Dir("./assets/dist/")))) + + log.Printf("HTTP server will now start listening on http://127.0.01:%d/\n", port) err := http.ListenAndServe(fmt.Sprintf(":%d", port), handlers.LoggingHandler(os.Stdout, r)) log.Println(err) } diff --git a/commands/users.go b/pkg/commands/users.go similarity index 81% rename from commands/users.go rename to pkg/commands/users.go index a751c55..972115e 100644 --- a/commands/users.go +++ b/pkg/commands/users.go @@ -1,8 +1,8 @@ package commands import ( - "github.com/dannyvankooten/ana/datastore" - "github.com/dannyvankooten/ana/models" + "github.com/dannyvankooten/ana/pkg/datastore" + "github.com/dannyvankooten/ana/pkg/models" "golang.org/x/crypto/bcrypt" "log" ) diff --git a/count/browsers.go b/pkg/count/browsers.go similarity index 97% rename from count/browsers.go rename to pkg/count/browsers.go index 42e556e..7d6636d 100644 --- a/count/browsers.go +++ b/pkg/count/browsers.go @@ -1,7 +1,7 @@ package count import ( - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/datastore" ) // TotalUniqueBrowsers returns the total # of unique browsers between two given timestamps diff --git a/count/count.go b/pkg/count/count.go similarity index 98% rename from count/count.go rename to pkg/count/count.go index a007c49..882b2f7 100644 --- a/count/count.go +++ b/pkg/count/count.go @@ -5,7 +5,7 @@ import ( "log" "time" - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/datastore" ) // Total represents a daily aggregated total for a metric diff --git a/count/count_test.go b/pkg/count/count_test.go similarity index 100% rename from count/count_test.go rename to pkg/count/count_test.go diff --git a/count/languages.go b/pkg/count/languages.go similarity index 97% rename from count/languages.go rename to pkg/count/languages.go index dba685b..2cdc21c 100644 --- a/count/languages.go +++ b/pkg/count/languages.go @@ -1,7 +1,7 @@ package count import ( - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/datastore" ) // TotalUniqueLanguages returns the total # of unique browser languages between two given timestamps diff --git a/count/pageviews.go b/pkg/count/pageviews.go similarity index 97% rename from count/pageviews.go rename to pkg/count/pageviews.go index b16ddc5..255b057 100644 --- a/count/pageviews.go +++ b/pkg/count/pageviews.go @@ -1,6 +1,6 @@ package count -import "github.com/dannyvankooten/ana/datastore" +import "github.com/dannyvankooten/ana/pkg/datastore" // Pageviews returns the total number of pageviews between the given timestamps func Pageviews(before int64, after int64) int { diff --git a/count/referrers.go b/pkg/count/referrers.go similarity index 97% rename from count/referrers.go rename to pkg/count/referrers.go index 08f7fbd..38ad940 100644 --- a/count/referrers.go +++ b/pkg/count/referrers.go @@ -1,7 +1,7 @@ package count import ( - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/datastore" ) // TotalReferrers returns the total # of referrers between two given timestamps diff --git a/count/screens.go b/pkg/count/screens.go similarity index 97% rename from count/screens.go rename to pkg/count/screens.go index e74c552..4be5550 100644 --- a/count/screens.go +++ b/pkg/count/screens.go @@ -1,7 +1,7 @@ package count import ( - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/datastore" ) // TotalUniqueScreens returns the total # of screens between two given timestamps diff --git a/count/visitors.go b/pkg/count/visitors.go similarity index 98% rename from count/visitors.go rename to pkg/count/visitors.go index 1e98e1a..2a3614e 100644 --- a/count/visitors.go +++ b/pkg/count/visitors.go @@ -1,7 +1,7 @@ package count import ( - "github.com/dannyvankooten/ana/datastore" + "github.com/dannyvankooten/ana/pkg/datastore" ) // RealtimeVisitors returns the total number of visitors in the last 3 minutes diff --git a/datastore/migrations/1_initial.sql b/pkg/datastore/migrations/1_initial.sql similarity index 100% rename from datastore/migrations/1_initial.sql rename to pkg/datastore/migrations/1_initial.sql diff --git a/datastore/options.go b/pkg/datastore/options.go similarity index 100% rename from datastore/options.go rename to pkg/datastore/options.go diff --git a/datastore/options_test.go b/pkg/datastore/options_test.go similarity index 100% rename from datastore/options_test.go rename to pkg/datastore/options_test.go diff --git a/datastore/pages.go b/pkg/datastore/pages.go similarity index 95% rename from datastore/pages.go rename to pkg/datastore/pages.go index 2fc0032..9c56ca1 100644 --- a/datastore/pages.go +++ b/pkg/datastore/pages.go @@ -1,7 +1,7 @@ package datastore import ( - "github.com/dannyvankooten/ana/models" + "github.com/dannyvankooten/ana/pkg/models" ) var p models.Page diff --git a/datastore/pageviews.go b/pkg/datastore/pageviews.go similarity index 96% rename from datastore/pageviews.go rename to pkg/datastore/pageviews.go index c71b715..80e302a 100644 --- a/datastore/pageviews.go +++ b/pkg/datastore/pageviews.go @@ -1,7 +1,7 @@ package datastore import ( - "github.com/dannyvankooten/ana/models" + "github.com/dannyvankooten/ana/pkg/models" ) //var pv models.Pageview diff --git a/datastore/seed.go b/pkg/datastore/seed.go similarity index 98% rename from datastore/seed.go rename to pkg/datastore/seed.go index 5b6e748..2ce9d40 100644 --- a/datastore/seed.go +++ b/pkg/datastore/seed.go @@ -8,7 +8,7 @@ import ( "time" randomdata "github.com/Pallinder/go-randomdata" - "github.com/dannyvankooten/ana/models" + "github.com/dannyvankooten/ana/pkg/models" ) var browserNames = []string{ diff --git a/datastore/store.go b/pkg/datastore/store.go similarity index 97% rename from datastore/store.go rename to pkg/datastore/store.go index 0bfd70b..dc2eb34 100644 --- a/datastore/store.go +++ b/pkg/datastore/store.go @@ -63,7 +63,7 @@ func getDSN(driver string) string { func runMigrations(driver string) { migrations := migrate.FileMigrationSource{ - Dir: "datastore/migrations", + Dir: "pkg/datastore/migrations", } migrate.SetTable("migrations") diff --git a/datastore/users.go b/pkg/datastore/users.go similarity index 93% rename from datastore/users.go rename to pkg/datastore/users.go index 85d98e6..e4f994a 100644 --- a/datastore/users.go +++ b/pkg/datastore/users.go @@ -1,7 +1,7 @@ package datastore import ( - "github.com/dannyvankooten/ana/models" + "github.com/dannyvankooten/ana/pkg/models" ) var u models.User diff --git a/datastore/visitors.go b/pkg/datastore/visitors.go similarity index 95% rename from datastore/visitors.go rename to pkg/datastore/visitors.go index 7a9a736..9cfe995 100644 --- a/datastore/visitors.go +++ b/pkg/datastore/visitors.go @@ -1,7 +1,7 @@ package datastore import ( - "github.com/dannyvankooten/ana/models" + "github.com/dannyvankooten/ana/pkg/models" ) var v models.Visitor diff --git a/models/page.go b/pkg/models/page.go similarity index 100% rename from models/page.go rename to pkg/models/page.go diff --git a/models/pageview.go b/pkg/models/pageview.go similarity index 100% rename from models/pageview.go rename to pkg/models/pageview.go diff --git a/models/user.go b/pkg/models/user.go similarity index 100% rename from models/user.go rename to pkg/models/user.go diff --git a/models/visitor.go b/pkg/models/visitor.go similarity index 100% rename from models/visitor.go rename to pkg/models/visitor.go diff --git a/vendor/github.com/alecthomas/template/LICENSE b/vendor/github.com/alecthomas/template/LICENSE new file mode 100644 index 0000000..7448756 --- /dev/null +++ b/vendor/github.com/alecthomas/template/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2012 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/alecthomas/template/README.md b/vendor/github.com/alecthomas/template/README.md new file mode 100644 index 0000000..ef6a8ee --- /dev/null +++ b/vendor/github.com/alecthomas/template/README.md @@ -0,0 +1,25 @@ +# Go's `text/template` package with newline elision + +This is a fork of Go 1.4's [text/template](http://golang.org/pkg/text/template/) package with one addition: a backslash immediately after a closing delimiter will delete all subsequent newlines until a non-newline. + +eg. + +``` +{{if true}}\ +hello +{{end}}\ +``` + +Will result in: + +``` +hello\n +``` + +Rather than: + +``` +\n +hello\n +\n +``` diff --git a/vendor/github.com/alecthomas/template/doc.go b/vendor/github.com/alecthomas/template/doc.go new file mode 100644 index 0000000..223c595 --- /dev/null +++ b/vendor/github.com/alecthomas/template/doc.go @@ -0,0 +1,406 @@ +// Copyright 2011 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. + +/* +Package template implements data-driven templates for generating textual output. + +To generate HTML output, see package html/template, which has the same interface +as this package but automatically secures HTML output against certain attacks. + +Templates are executed by applying them to a data structure. Annotations in the +template refer to elements of the data structure (typically a field of a struct +or a key in a map) to control execution and derive values to be displayed. +Execution of the template walks the structure and sets the cursor, represented +by a period '.' and called "dot", to the value at the current location in the +structure as execution proceeds. + +The input text for a template is UTF-8-encoded text in any format. +"Actions"--data evaluations or control structures--are delimited by +"{{" and "}}"; all text outside actions is copied to the output unchanged. +Actions may not span newlines, although comments can. + +Once parsed, a template may be executed safely in parallel. + +Here is a trivial example that prints "17 items are made of wool". + + type Inventory struct { + Material string + Count uint + } + sweaters := Inventory{"wool", 17} + tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}") + if err != nil { panic(err) } + err = tmpl.Execute(os.Stdout, sweaters) + if err != nil { panic(err) } + +More intricate examples appear below. + +Actions + +Here is the list of actions. "Arguments" and "pipelines" are evaluations of +data, defined in detail below. + +*/ +// {{/* a comment */}} +// A comment; discarded. May contain newlines. +// Comments do not nest and must start and end at the +// delimiters, as shown here. +/* + + {{pipeline}} + The default textual representation of the value of the pipeline + is copied to the output. + + {{if pipeline}} T1 {{end}} + If the value of the pipeline is empty, no output is generated; + otherwise, T1 is executed. The empty values are false, 0, any + nil pointer or interface value, and any array, slice, map, or + string of length zero. + Dot is unaffected. + + {{if pipeline}} T1 {{else}} T0 {{end}} + If the value of the pipeline is empty, T0 is executed; + otherwise, T1 is executed. Dot is unaffected. + + {{if pipeline}} T1 {{else if pipeline}} T0 {{end}} + To simplify the appearance of if-else chains, the else action + of an if may include another if directly; the effect is exactly + the same as writing + {{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}} + + {{range pipeline}} T1 {{end}} + The value of the pipeline must be an array, slice, map, or channel. + If the value of the pipeline has length zero, nothing is output; + otherwise, dot is set to the successive elements of the array, + slice, or map and T1 is executed. If the value is a map and the + keys are of basic type with a defined order ("comparable"), the + elements will be visited in sorted key order. + + {{range pipeline}} T1 {{else}} T0 {{end}} + The value of the pipeline must be an array, slice, map, or channel. + If the value of the pipeline has length zero, dot is unaffected and + T0 is executed; otherwise, dot is set to the successive elements + of the array, slice, or map and T1 is executed. + + {{template "name"}} + The template with the specified name is executed with nil data. + + {{template "name" pipeline}} + The template with the specified name is executed with dot set + to the value of the pipeline. + + {{with pipeline}} T1 {{end}} + If the value of the pipeline is empty, no output is generated; + otherwise, dot is set to the value of the pipeline and T1 is + executed. + + {{with pipeline}} T1 {{else}} T0 {{end}} + If the value of the pipeline is empty, dot is unaffected and T0 + is executed; otherwise, dot is set to the value of the pipeline + and T1 is executed. + +Arguments + +An argument is a simple value, denoted by one of the following. + + - A boolean, string, character, integer, floating-point, imaginary + or complex constant in Go syntax. These behave like Go's untyped + constants, although raw strings may not span newlines. + - The keyword nil, representing an untyped Go nil. + - The character '.' (period): + . + The result is the value of dot. + - A variable name, which is a (possibly empty) alphanumeric string + preceded by a dollar sign, such as + $piOver2 + or + $ + The result is the value of the variable. + Variables are described below. + - The name of a field of the data, which must be a struct, preceded + by a period, such as + .Field + The result is the value of the field. Field invocations may be + chained: + .Field1.Field2 + Fields can also be evaluated on variables, including chaining: + $x.Field1.Field2 + - The name of a key of the data, which must be a map, preceded + by a period, such as + .Key + The result is the map element value indexed by the key. + Key invocations may be chained and combined with fields to any + depth: + .Field1.Key1.Field2.Key2 + Although the key must be an alphanumeric identifier, unlike with + field names they do not need to start with an upper case letter. + Keys can also be evaluated on variables, including chaining: + $x.key1.key2 + - The name of a niladic method of the data, preceded by a period, + such as + .Method + The result is the value of invoking the method with dot as the + receiver, dot.Method(). Such a method must have one return value (of + any type) or two return values, the second of which is an error. + If it has two and the returned error is non-nil, execution terminates + and an error is returned to the caller as the value of Execute. + Method invocations may be chained and combined with fields and keys + to any depth: + .Field1.Key1.Method1.Field2.Key2.Method2 + Methods can also be evaluated on variables, including chaining: + $x.Method1.Field + - The name of a niladic function, such as + fun + The result is the value of invoking the function, fun(). The return + types and values behave as in methods. Functions and function + names are described below. + - A parenthesized instance of one the above, for grouping. The result + may be accessed by a field or map key invocation. + print (.F1 arg1) (.F2 arg2) + (.StructValuedMethod "arg").Field + +Arguments may evaluate to any type; if they are pointers the implementation +automatically indirects to the base type when required. +If an evaluation yields a function value, such as a function-valued +field of a struct, the function is not invoked automatically, but it +can be used as a truth value for an if action and the like. To invoke +it, use the call function, defined below. + +A pipeline is a possibly chained sequence of "commands". A command is a simple +value (argument) or a function or method call, possibly with multiple arguments: + + Argument + The result is the value of evaluating the argument. + .Method [Argument...] + The method can be alone or the last element of a chain but, + unlike methods in the middle of a chain, it can take arguments. + The result is the value of calling the method with the + arguments: + dot.Method(Argument1, etc.) + functionName [Argument...] + The result is the value of calling the function associated + with the name: + function(Argument1, etc.) + Functions and function names are described below. + +Pipelines + +A pipeline may be "chained" by separating a sequence of commands with pipeline +characters '|'. In a chained pipeline, the result of the each command is +passed as the last argument of the following command. The output of the final +command in the pipeline is the value of the pipeline. + +The output of a command will be either one value or two values, the second of +which has type error. If that second value is present and evaluates to +non-nil, execution terminates and the error is returned to the caller of +Execute. + +Variables + +A pipeline inside an action may initialize a variable to capture the result. +The initialization has syntax + + $variable := pipeline + +where $variable is the name of the variable. An action that declares a +variable produces no output. + +If a "range" action initializes a variable, the variable is set to the +successive elements of the iteration. Also, a "range" may declare two +variables, separated by a comma: + + range $index, $element := pipeline + +in which case $index and $element are set to the successive values of the +array/slice index or map key and element, respectively. Note that if there is +only one variable, it is assigned the element; this is opposite to the +convention in Go range clauses. + +A variable's scope extends to the "end" action of the control structure ("if", +"with", or "range") in which it is declared, or to the end of the template if +there is no such control structure. A template invocation does not inherit +variables from the point of its invocation. + +When execution begins, $ is set to the data argument passed to Execute, that is, +to the starting value of dot. + +Examples + +Here are some example one-line templates demonstrating pipelines and variables. +All produce the quoted word "output": + + {{"\"output\""}} + A string constant. + {{`"output"`}} + A raw string constant. + {{printf "%q" "output"}} + A function call. + {{"output" | printf "%q"}} + A function call whose final argument comes from the previous + command. + {{printf "%q" (print "out" "put")}} + A parenthesized argument. + {{"put" | printf "%s%s" "out" | printf "%q"}} + A more elaborate call. + {{"output" | printf "%s" | printf "%q"}} + A longer chain. + {{with "output"}}{{printf "%q" .}}{{end}} + A with action using dot. + {{with $x := "output" | printf "%q"}}{{$x}}{{end}} + A with action that creates and uses a variable. + {{with $x := "output"}}{{printf "%q" $x}}{{end}} + A with action that uses the variable in another action. + {{with $x := "output"}}{{$x | printf "%q"}}{{end}} + The same, but pipelined. + +Functions + +During execution functions are found in two function maps: first in the +template, then in the global function map. By default, no functions are defined +in the template but the Funcs method can be used to add them. + +Predefined global functions are named as follows. + + and + Returns the boolean AND of its arguments by returning the + first empty argument or the last argument, that is, + "and x y" behaves as "if x then y else x". All the + arguments are evaluated. + call + Returns the result of calling the first argument, which + must be a function, with the remaining arguments as parameters. + Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where + Y is a func-valued field, map entry, or the like. + The first argument must be the result of an evaluation + that yields a value of function type (as distinct from + a predefined function such as print). The function must + return either one or two result values, the second of which + is of type error. If the arguments don't match the function + or the returned error value is non-nil, execution stops. + html + Returns the escaped HTML equivalent of the textual + representation of its arguments. + index + Returns the result of indexing its first argument by the + following arguments. Thus "index x 1 2 3" is, in Go syntax, + x[1][2][3]. Each indexed item must be a map, slice, or array. + js + Returns the escaped JavaScript equivalent of the textual + representation of its arguments. + len + Returns the integer length of its argument. + not + Returns the boolean negation of its single argument. + or + Returns the boolean OR of its arguments by returning the + first non-empty argument or the last argument, that is, + "or x y" behaves as "if x then x else y". All the + arguments are evaluated. + print + An alias for fmt.Sprint + printf + An alias for fmt.Sprintf + println + An alias for fmt.Sprintln + urlquery + Returns the escaped value of the textual representation of + its arguments in a form suitable for embedding in a URL query. + +The boolean functions take any zero value to be false and a non-zero +value to be true. + +There is also a set of binary comparison operators defined as +functions: + + eq + Returns the boolean truth of arg1 == arg2 + ne + Returns the boolean truth of arg1 != arg2 + lt + Returns the boolean truth of arg1 < arg2 + le + Returns the boolean truth of arg1 <= arg2 + gt + Returns the boolean truth of arg1 > arg2 + ge + Returns the boolean truth of arg1 >= arg2 + +For simpler multi-way equality tests, eq (only) accepts two or more +arguments and compares the second and subsequent to the first, +returning in effect + + arg1==arg2 || arg1==arg3 || arg1==arg4 ... + +(Unlike with || in Go, however, eq is a function call and all the +arguments will be evaluated.) + +The comparison functions work on basic types only (or named basic +types, such as "type Celsius float32"). They implement the Go rules +for comparison of values, except that size and exact type are +ignored, so any integer value, signed or unsigned, may be compared +with any other integer value. (The arithmetic value is compared, +not the bit pattern, so all negative integers are less than all +unsigned integers.) However, as usual, one may not compare an int +with a float32 and so on. + +Associated templates + +Each template is named by a string specified when it is created. Also, each +template is associated with zero or more other templates that it may invoke by +name; such associations are transitive and form a name space of templates. + +A template may use a template invocation to instantiate another associated +template; see the explanation of the "template" action above. The name must be +that of a template associated with the template that contains the invocation. + +Nested template definitions + +When parsing a template, another template may be defined and associated with the +template being parsed. Template definitions must appear at the top level of the +template, much like global variables in a Go program. + +The syntax of such definitions is to surround each template declaration with a +"define" and "end" action. + +The define action names the template being created by providing a string +constant. Here is a simple example: + + `{{define "T1"}}ONE{{end}} + {{define "T2"}}TWO{{end}} + {{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}} + {{template "T3"}}` + +This defines two templates, T1 and T2, and a third T3 that invokes the other two +when it is executed. Finally it invokes T3. If executed this template will +produce the text + + ONE TWO + +By construction, a template may reside in only one association. If it's +necessary to have a template addressable from multiple associations, the +template definition must be parsed multiple times to create distinct *Template +values, or must be copied with the Clone or AddParseTree method. + +Parse may be called multiple times to assemble the various associated templates; +see the ParseFiles and ParseGlob functions and methods for simple ways to parse +related templates stored in files. + +A template may be executed directly or through ExecuteTemplate, which executes +an associated template identified by name. To invoke our example above, we +might write, + + err := tmpl.Execute(os.Stdout, "no data needed") + if err != nil { + log.Fatalf("execution failed: %s", err) + } + +or to invoke a particular template explicitly by name, + + err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed") + if err != nil { + log.Fatalf("execution failed: %s", err) + } + +*/ +package template diff --git a/vendor/github.com/alecthomas/template/exec.go b/vendor/github.com/alecthomas/template/exec.go new file mode 100644 index 0000000..c3078e5 --- /dev/null +++ b/vendor/github.com/alecthomas/template/exec.go @@ -0,0 +1,845 @@ +// Copyright 2011 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. + +package template + +import ( + "bytes" + "fmt" + "io" + "reflect" + "runtime" + "sort" + "strings" + + "github.com/alecthomas/template/parse" +) + +// state represents the state of an execution. It's not part of the +// template so that multiple executions of the same template +// can execute in parallel. +type state struct { + tmpl *Template + wr io.Writer + node parse.Node // current node, for errors + vars []variable // push-down stack of variable values. +} + +// variable holds the dynamic value of a variable such as $, $x etc. +type variable struct { + name string + value reflect.Value +} + +// push pushes a new variable on the stack. +func (s *state) push(name string, value reflect.Value) { + s.vars = append(s.vars, variable{name, value}) +} + +// mark returns the length of the variable stack. +func (s *state) mark() int { + return len(s.vars) +} + +// pop pops the variable stack up to the mark. +func (s *state) pop(mark int) { + s.vars = s.vars[0:mark] +} + +// setVar overwrites the top-nth variable on the stack. Used by range iterations. +func (s *state) setVar(n int, value reflect.Value) { + s.vars[len(s.vars)-n].value = value +} + +// varValue returns the value of the named variable. +func (s *state) varValue(name string) reflect.Value { + for i := s.mark() - 1; i >= 0; i-- { + if s.vars[i].name == name { + return s.vars[i].value + } + } + s.errorf("undefined variable: %s", name) + return zero +} + +var zero reflect.Value + +// at marks the state to be on node n, for error reporting. +func (s *state) at(node parse.Node) { + s.node = node +} + +// doublePercent returns the string with %'s replaced by %%, if necessary, +// so it can be used safely inside a Printf format string. +func doublePercent(str string) string { + if strings.Contains(str, "%") { + str = strings.Replace(str, "%", "%%", -1) + } + return str +} + +// errorf formats the error and terminates processing. +func (s *state) errorf(format string, args ...interface{}) { + name := doublePercent(s.tmpl.Name()) + if s.node == nil { + format = fmt.Sprintf("template: %s: %s", name, format) + } else { + location, context := s.tmpl.ErrorContext(s.node) + format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format) + } + panic(fmt.Errorf(format, args...)) +} + +// errRecover is the handler that turns panics into returns from the top +// level of Parse. +func errRecover(errp *error) { + e := recover() + if e != nil { + switch err := e.(type) { + case runtime.Error: + panic(e) + case error: + *errp = err + default: + panic(e) + } + } +} + +// ExecuteTemplate applies the template associated with t that has the given name +// to the specified data object and writes the output to wr. +// If an error occurs executing the template or writing its output, +// execution stops, but partial results may already have been written to +// the output writer. +// A template may be executed safely in parallel. +func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { + tmpl := t.tmpl[name] + if tmpl == nil { + return fmt.Errorf("template: no template %q associated with template %q", name, t.name) + } + return tmpl.Execute(wr, data) +} + +// Execute applies a parsed template to the specified data object, +// and writes the output to wr. +// If an error occurs executing the template or writing its output, +// execution stops, but partial results may already have been written to +// the output writer. +// A template may be executed safely in parallel. +func (t *Template) Execute(wr io.Writer, data interface{}) (err error) { + defer errRecover(&err) + value := reflect.ValueOf(data) + state := &state{ + tmpl: t, + wr: wr, + vars: []variable{{"$", value}}, + } + t.init() + if t.Tree == nil || t.Root == nil { + var b bytes.Buffer + for name, tmpl := range t.tmpl { + if tmpl.Tree == nil || tmpl.Root == nil { + continue + } + if b.Len() > 0 { + b.WriteString(", ") + } + fmt.Fprintf(&b, "%q", name) + } + var s string + if b.Len() > 0 { + s = "; defined templates are: " + b.String() + } + state.errorf("%q is an incomplete or empty template%s", t.Name(), s) + } + state.walk(value, t.Root) + return +} + +// Walk functions step through the major pieces of the template structure, +// generating output as they go. +func (s *state) walk(dot reflect.Value, node parse.Node) { + s.at(node) + switch node := node.(type) { + case *parse.ActionNode: + // Do not pop variables so they persist until next end. + // Also, if the action declares variables, don't print the result. + val := s.evalPipeline(dot, node.Pipe) + if len(node.Pipe.Decl) == 0 { + s.printValue(node, val) + } + case *parse.IfNode: + s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList) + case *parse.ListNode: + for _, node := range node.Nodes { + s.walk(dot, node) + } + case *parse.RangeNode: + s.walkRange(dot, node) + case *parse.TemplateNode: + s.walkTemplate(dot, node) + case *parse.TextNode: + if _, err := s.wr.Write(node.Text); err != nil { + s.errorf("%s", err) + } + case *parse.WithNode: + s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList) + default: + s.errorf("unknown node: %s", node) + } +} + +// walkIfOrWith walks an 'if' or 'with' node. The two control structures +// are identical in behavior except that 'with' sets dot. +func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) { + defer s.pop(s.mark()) + val := s.evalPipeline(dot, pipe) + truth, ok := isTrue(val) + if !ok { + s.errorf("if/with can't use %v", val) + } + if truth { + if typ == parse.NodeWith { + s.walk(val, list) + } else { + s.walk(dot, list) + } + } else if elseList != nil { + s.walk(dot, elseList) + } +} + +// isTrue reports whether the value is 'true', in the sense of not the zero of its type, +// and whether the value has a meaningful truth value. +func isTrue(val reflect.Value) (truth, ok bool) { + if !val.IsValid() { + // Something like var x interface{}, never set. It's a form of nil. + return false, true + } + switch val.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + truth = val.Len() > 0 + case reflect.Bool: + truth = val.Bool() + case reflect.Complex64, reflect.Complex128: + truth = val.Complex() != 0 + case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: + truth = !val.IsNil() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + truth = val.Int() != 0 + case reflect.Float32, reflect.Float64: + truth = val.Float() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + truth = val.Uint() != 0 + case reflect.Struct: + truth = true // Struct values are always true. + default: + return + } + return truth, true +} + +func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) { + s.at(r) + defer s.pop(s.mark()) + val, _ := indirect(s.evalPipeline(dot, r.Pipe)) + // mark top of stack before any variables in the body are pushed. + mark := s.mark() + oneIteration := func(index, elem reflect.Value) { + // Set top var (lexically the second if there are two) to the element. + if len(r.Pipe.Decl) > 0 { + s.setVar(1, elem) + } + // Set next var (lexically the first if there are two) to the index. + if len(r.Pipe.Decl) > 1 { + s.setVar(2, index) + } + s.walk(elem, r.List) + s.pop(mark) + } + switch val.Kind() { + case reflect.Array, reflect.Slice: + if val.Len() == 0 { + break + } + for i := 0; i < val.Len(); i++ { + oneIteration(reflect.ValueOf(i), val.Index(i)) + } + return + case reflect.Map: + if val.Len() == 0 { + break + } + for _, key := range sortKeys(val.MapKeys()) { + oneIteration(key, val.MapIndex(key)) + } + return + case reflect.Chan: + if val.IsNil() { + break + } + i := 0 + for ; ; i++ { + elem, ok := val.Recv() + if !ok { + break + } + oneIteration(reflect.ValueOf(i), elem) + } + if i == 0 { + break + } + return + case reflect.Invalid: + break // An invalid value is likely a nil map, etc. and acts like an empty map. + default: + s.errorf("range can't iterate over %v", val) + } + if r.ElseList != nil { + s.walk(dot, r.ElseList) + } +} + +func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) { + s.at(t) + tmpl := s.tmpl.tmpl[t.Name] + if tmpl == nil { + s.errorf("template %q not defined", t.Name) + } + // Variables declared by the pipeline persist. + dot = s.evalPipeline(dot, t.Pipe) + newState := *s + newState.tmpl = tmpl + // No dynamic scoping: template invocations inherit no variables. + newState.vars = []variable{{"$", dot}} + newState.walk(dot, tmpl.Root) +} + +// Eval functions evaluate pipelines, commands, and their elements and extract +// values from the data structure by examining fields, calling methods, and so on. +// The printing of those values happens only through walk functions. + +// evalPipeline returns the value acquired by evaluating a pipeline. If the +// pipeline has a variable declaration, the variable will be pushed on the +// stack. Callers should therefore pop the stack after they are finished +// executing commands depending on the pipeline value. +func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) { + if pipe == nil { + return + } + s.at(pipe) + for _, cmd := range pipe.Cmds { + value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg. + // If the object has type interface{}, dig down one level to the thing inside. + if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 { + value = reflect.ValueOf(value.Interface()) // lovely! + } + } + for _, variable := range pipe.Decl { + s.push(variable.Ident[0], value) + } + return value +} + +func (s *state) notAFunction(args []parse.Node, final reflect.Value) { + if len(args) > 1 || final.IsValid() { + s.errorf("can't give argument to non-function %s", args[0]) + } +} + +func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value { + firstWord := cmd.Args[0] + switch n := firstWord.(type) { + case *parse.FieldNode: + return s.evalFieldNode(dot, n, cmd.Args, final) + case *parse.ChainNode: + return s.evalChainNode(dot, n, cmd.Args, final) + case *parse.IdentifierNode: + // Must be a function. + return s.evalFunction(dot, n, cmd, cmd.Args, final) + case *parse.PipeNode: + // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored. + return s.evalPipeline(dot, n) + case *parse.VariableNode: + return s.evalVariableNode(dot, n, cmd.Args, final) + } + s.at(firstWord) + s.notAFunction(cmd.Args, final) + switch word := firstWord.(type) { + case *parse.BoolNode: + return reflect.ValueOf(word.True) + case *parse.DotNode: + return dot + case *parse.NilNode: + s.errorf("nil is not a command") + case *parse.NumberNode: + return s.idealConstant(word) + case *parse.StringNode: + return reflect.ValueOf(word.Text) + } + s.errorf("can't evaluate command %q", firstWord) + panic("not reached") +} + +// idealConstant is called to return the value of a number in a context where +// we don't know the type. In that case, the syntax of the number tells us +// its type, and we use Go rules to resolve. Note there is no such thing as +// a uint ideal constant in this situation - the value must be of int type. +func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value { + // These are ideal constants but we don't know the type + // and we have no context. (If it was a method argument, + // we'd know what we need.) The syntax guides us to some extent. + s.at(constant) + switch { + case constant.IsComplex: + return reflect.ValueOf(constant.Complex128) // incontrovertible. + case constant.IsFloat && !isHexConstant(constant.Text) && strings.IndexAny(constant.Text, ".eE") >= 0: + return reflect.ValueOf(constant.Float64) + case constant.IsInt: + n := int(constant.Int64) + if int64(n) != constant.Int64 { + s.errorf("%s overflows int", constant.Text) + } + return reflect.ValueOf(n) + case constant.IsUint: + s.errorf("%s overflows int", constant.Text) + } + return zero +} + +func isHexConstant(s string) bool { + return len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') +} + +func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value { + s.at(field) + return s.evalFieldChain(dot, dot, field, field.Ident, args, final) +} + +func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value { + s.at(chain) + // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields. + pipe := s.evalArg(dot, nil, chain.Node) + if len(chain.Field) == 0 { + s.errorf("internal error: no fields in evalChainNode") + } + return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final) +} + +func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value { + // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields. + s.at(variable) + value := s.varValue(variable.Ident[0]) + if len(variable.Ident) == 1 { + s.notAFunction(args, final) + return value + } + return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final) +} + +// evalFieldChain evaluates .X.Y.Z possibly followed by arguments. +// dot is the environment in which to evaluate arguments, while +// receiver is the value being walked along the chain. +func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value { + n := len(ident) + for i := 0; i < n-1; i++ { + receiver = s.evalField(dot, ident[i], node, nil, zero, receiver) + } + // Now if it's a method, it gets the arguments. + return s.evalField(dot, ident[n-1], node, args, final, receiver) +} + +func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value { + s.at(node) + name := node.Ident + function, ok := findFunction(name, s.tmpl) + if !ok { + s.errorf("%q is not a defined function", name) + } + return s.evalCall(dot, function, cmd, name, args, final) +} + +// evalField evaluates an expression like (.Field) or (.Field arg1 arg2). +// The 'final' argument represents the return value from the preceding +// value of the pipeline, if any. +func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value { + if !receiver.IsValid() { + return zero + } + typ := receiver.Type() + receiver, _ = indirect(receiver) + // Unless it's an interface, need to get to a value of type *T to guarantee + // we see all methods of T and *T. + ptr := receiver + if ptr.Kind() != reflect.Interface && ptr.CanAddr() { + ptr = ptr.Addr() + } + if method := ptr.MethodByName(fieldName); method.IsValid() { + return s.evalCall(dot, method, node, fieldName, args, final) + } + hasArgs := len(args) > 1 || final.IsValid() + // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil. + receiver, isNil := indirect(receiver) + if isNil { + s.errorf("nil pointer evaluating %s.%s", typ, fieldName) + } + switch receiver.Kind() { + case reflect.Struct: + tField, ok := receiver.Type().FieldByName(fieldName) + if ok { + field := receiver.FieldByIndex(tField.Index) + if tField.PkgPath != "" { // field is unexported + s.errorf("%s is an unexported field of struct type %s", fieldName, typ) + } + // If it's a function, we must call it. + if hasArgs { + s.errorf("%s has arguments but cannot be invoked as function", fieldName) + } + return field + } + s.errorf("%s is not a field of struct type %s", fieldName, typ) + case reflect.Map: + // If it's a map, attempt to use the field name as a key. + nameVal := reflect.ValueOf(fieldName) + if nameVal.Type().AssignableTo(receiver.Type().Key()) { + if hasArgs { + s.errorf("%s is not a method but has arguments", fieldName) + } + return receiver.MapIndex(nameVal) + } + } + s.errorf("can't evaluate field %s in type %s", fieldName, typ) + panic("not reached") +} + +var ( + errorType = reflect.TypeOf((*error)(nil)).Elem() + fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() +) + +// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so +// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0] +// as the function itself. +func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value { + if args != nil { + args = args[1:] // Zeroth arg is function name/node; not passed to function. + } + typ := fun.Type() + numIn := len(args) + if final.IsValid() { + numIn++ + } + numFixed := len(args) + if typ.IsVariadic() { + numFixed = typ.NumIn() - 1 // last arg is the variadic one. + if numIn < numFixed { + s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args)) + } + } else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() { + s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args)) + } + if !goodFunc(typ) { + // TODO: This could still be a confusing error; maybe goodFunc should provide info. + s.errorf("can't call method/function %q with %d results", name, typ.NumOut()) + } + // Build the arg list. + argv := make([]reflect.Value, numIn) + // Args must be evaluated. Fixed args first. + i := 0 + for ; i < numFixed && i < len(args); i++ { + argv[i] = s.evalArg(dot, typ.In(i), args[i]) + } + // Now the ... args. + if typ.IsVariadic() { + argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice. + for ; i < len(args); i++ { + argv[i] = s.evalArg(dot, argType, args[i]) + } + } + // Add final value if necessary. + if final.IsValid() { + t := typ.In(typ.NumIn() - 1) + if typ.IsVariadic() { + t = t.Elem() + } + argv[i] = s.validateType(final, t) + } + result := fun.Call(argv) + // If we have an error that is not nil, stop execution and return that error to the caller. + if len(result) == 2 && !result[1].IsNil() { + s.at(node) + s.errorf("error calling %s: %s", name, result[1].Interface().(error)) + } + return result[0] +} + +// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero. +func canBeNil(typ reflect.Type) bool { + switch typ.Kind() { + case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: + return true + } + return false +} + +// validateType guarantees that the value is valid and assignable to the type. +func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value { + if !value.IsValid() { + if typ == nil || canBeNil(typ) { + // An untyped nil interface{}. Accept as a proper nil value. + return reflect.Zero(typ) + } + s.errorf("invalid value; expected %s", typ) + } + if typ != nil && !value.Type().AssignableTo(typ) { + if value.Kind() == reflect.Interface && !value.IsNil() { + value = value.Elem() + if value.Type().AssignableTo(typ) { + return value + } + // fallthrough + } + // Does one dereference or indirection work? We could do more, as we + // do with method receivers, but that gets messy and method receivers + // are much more constrained, so it makes more sense there than here. + // Besides, one is almost always all you need. + switch { + case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ): + value = value.Elem() + if !value.IsValid() { + s.errorf("dereference of nil pointer of type %s", typ) + } + case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr(): + value = value.Addr() + default: + s.errorf("wrong type for value; expected %s; got %s", typ, value.Type()) + } + } + return value +} + +func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + switch arg := n.(type) { + case *parse.DotNode: + return s.validateType(dot, typ) + case *parse.NilNode: + if canBeNil(typ) { + return reflect.Zero(typ) + } + s.errorf("cannot assign nil to %s", typ) + case *parse.FieldNode: + return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ) + case *parse.VariableNode: + return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ) + case *parse.PipeNode: + return s.validateType(s.evalPipeline(dot, arg), typ) + case *parse.IdentifierNode: + return s.evalFunction(dot, arg, arg, nil, zero) + case *parse.ChainNode: + return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ) + } + switch typ.Kind() { + case reflect.Bool: + return s.evalBool(typ, n) + case reflect.Complex64, reflect.Complex128: + return s.evalComplex(typ, n) + case reflect.Float32, reflect.Float64: + return s.evalFloat(typ, n) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return s.evalInteger(typ, n) + case reflect.Interface: + if typ.NumMethod() == 0 { + return s.evalEmptyInterface(dot, n) + } + case reflect.String: + return s.evalString(typ, n) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return s.evalUnsignedInteger(typ, n) + } + s.errorf("can't handle %s for arg of type %s", n, typ) + panic("not reached") +} + +func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.BoolNode); ok { + value := reflect.New(typ).Elem() + value.SetBool(n.True) + return value + } + s.errorf("expected bool; found %s", n) + panic("not reached") +} + +func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.StringNode); ok { + value := reflect.New(typ).Elem() + value.SetString(n.Text) + return value + } + s.errorf("expected string; found %s", n) + panic("not reached") +} + +func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.NumberNode); ok && n.IsInt { + value := reflect.New(typ).Elem() + value.SetInt(n.Int64) + return value + } + s.errorf("expected integer; found %s", n) + panic("not reached") +} + +func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.NumberNode); ok && n.IsUint { + value := reflect.New(typ).Elem() + value.SetUint(n.Uint64) + return value + } + s.errorf("expected unsigned integer; found %s", n) + panic("not reached") +} + +func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value { + s.at(n) + if n, ok := n.(*parse.NumberNode); ok && n.IsFloat { + value := reflect.New(typ).Elem() + value.SetFloat(n.Float64) + return value + } + s.errorf("expected float; found %s", n) + panic("not reached") +} + +func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value { + if n, ok := n.(*parse.NumberNode); ok && n.IsComplex { + value := reflect.New(typ).Elem() + value.SetComplex(n.Complex128) + return value + } + s.errorf("expected complex; found %s", n) + panic("not reached") +} + +func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value { + s.at(n) + switch n := n.(type) { + case *parse.BoolNode: + return reflect.ValueOf(n.True) + case *parse.DotNode: + return dot + case *parse.FieldNode: + return s.evalFieldNode(dot, n, nil, zero) + case *parse.IdentifierNode: + return s.evalFunction(dot, n, n, nil, zero) + case *parse.NilNode: + // NilNode is handled in evalArg, the only place that calls here. + s.errorf("evalEmptyInterface: nil (can't happen)") + case *parse.NumberNode: + return s.idealConstant(n) + case *parse.StringNode: + return reflect.ValueOf(n.Text) + case *parse.VariableNode: + return s.evalVariableNode(dot, n, nil, zero) + case *parse.PipeNode: + return s.evalPipeline(dot, n) + } + s.errorf("can't handle assignment of %s to empty interface argument", n) + panic("not reached") +} + +// indirect returns the item at the end of indirection, and a bool to indicate if it's nil. +// We indirect through pointers and empty interfaces (only) because +// non-empty interfaces have methods we might need. +func indirect(v reflect.Value) (rv reflect.Value, isNil bool) { + for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() { + if v.IsNil() { + return v, true + } + if v.Kind() == reflect.Interface && v.NumMethod() > 0 { + break + } + } + return v, false +} + +// printValue writes the textual representation of the value to the output of +// the template. +func (s *state) printValue(n parse.Node, v reflect.Value) { + s.at(n) + iface, ok := printableValue(v) + if !ok { + s.errorf("can't print %s of type %s", n, v.Type()) + } + fmt.Fprint(s.wr, iface) +} + +// printableValue returns the, possibly indirected, interface value inside v that +// is best for a call to formatted printer. +func printableValue(v reflect.Value) (interface{}, bool) { + if v.Kind() == reflect.Ptr { + v, _ = indirect(v) // fmt.Fprint handles nil. + } + if !v.IsValid() { + return "", true + } + + if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) { + if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) { + v = v.Addr() + } else { + switch v.Kind() { + case reflect.Chan, reflect.Func: + return nil, false + } + } + } + return v.Interface(), true +} + +// Types to help sort the keys in a map for reproducible output. + +type rvs []reflect.Value + +func (x rvs) Len() int { return len(x) } +func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] } + +type rvInts struct{ rvs } + +func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() } + +type rvUints struct{ rvs } + +func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() } + +type rvFloats struct{ rvs } + +func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() } + +type rvStrings struct{ rvs } + +func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() } + +// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys. +func sortKeys(v []reflect.Value) []reflect.Value { + if len(v) <= 1 { + return v + } + switch v[0].Kind() { + case reflect.Float32, reflect.Float64: + sort.Sort(rvFloats{v}) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + sort.Sort(rvInts{v}) + case reflect.String: + sort.Sort(rvStrings{v}) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + sort.Sort(rvUints{v}) + } + return v +} diff --git a/vendor/github.com/alecthomas/template/funcs.go b/vendor/github.com/alecthomas/template/funcs.go new file mode 100644 index 0000000..39ee5ed --- /dev/null +++ b/vendor/github.com/alecthomas/template/funcs.go @@ -0,0 +1,598 @@ +// Copyright 2011 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. + +package template + +import ( + "bytes" + "errors" + "fmt" + "io" + "net/url" + "reflect" + "strings" + "unicode" + "unicode/utf8" +) + +// FuncMap is the type of the map defining the mapping from names to functions. +// Each function must have either a single return value, or two return values of +// which the second has type error. In that case, if the second (error) +// return value evaluates to non-nil during execution, execution terminates and +// Execute returns that error. +type FuncMap map[string]interface{} + +var builtins = FuncMap{ + "and": and, + "call": call, + "html": HTMLEscaper, + "index": index, + "js": JSEscaper, + "len": length, + "not": not, + "or": or, + "print": fmt.Sprint, + "printf": fmt.Sprintf, + "println": fmt.Sprintln, + "urlquery": URLQueryEscaper, + + // Comparisons + "eq": eq, // == + "ge": ge, // >= + "gt": gt, // > + "le": le, // <= + "lt": lt, // < + "ne": ne, // != +} + +var builtinFuncs = createValueFuncs(builtins) + +// createValueFuncs turns a FuncMap into a map[string]reflect.Value +func createValueFuncs(funcMap FuncMap) map[string]reflect.Value { + m := make(map[string]reflect.Value) + addValueFuncs(m, funcMap) + return m +} + +// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values. +func addValueFuncs(out map[string]reflect.Value, in FuncMap) { + for name, fn := range in { + v := reflect.ValueOf(fn) + if v.Kind() != reflect.Func { + panic("value for " + name + " not a function") + } + if !goodFunc(v.Type()) { + panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut())) + } + out[name] = v + } +} + +// addFuncs adds to values the functions in funcs. It does no checking of the input - +// call addValueFuncs first. +func addFuncs(out, in FuncMap) { + for name, fn := range in { + out[name] = fn + } +} + +// goodFunc checks that the function or method has the right result signature. +func goodFunc(typ reflect.Type) bool { + // We allow functions with 1 result or 2 results where the second is an error. + switch { + case typ.NumOut() == 1: + return true + case typ.NumOut() == 2 && typ.Out(1) == errorType: + return true + } + return false +} + +// findFunction looks for a function in the template, and global map. +func findFunction(name string, tmpl *Template) (reflect.Value, bool) { + if tmpl != nil && tmpl.common != nil { + if fn := tmpl.execFuncs[name]; fn.IsValid() { + return fn, true + } + } + if fn := builtinFuncs[name]; fn.IsValid() { + return fn, true + } + return reflect.Value{}, false +} + +// Indexing. + +// index returns the result of indexing its first argument by the following +// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each +// indexed item must be a map, slice, or array. +func index(item interface{}, indices ...interface{}) (interface{}, error) { + v := reflect.ValueOf(item) + for _, i := range indices { + index := reflect.ValueOf(i) + var isNil bool + if v, isNil = indirect(v); isNil { + return nil, fmt.Errorf("index of nil pointer") + } + switch v.Kind() { + case reflect.Array, reflect.Slice, reflect.String: + var x int64 + switch index.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + x = index.Int() + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + x = int64(index.Uint()) + default: + return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type()) + } + if x < 0 || x >= int64(v.Len()) { + return nil, fmt.Errorf("index out of range: %d", x) + } + v = v.Index(int(x)) + case reflect.Map: + if !index.IsValid() { + index = reflect.Zero(v.Type().Key()) + } + if !index.Type().AssignableTo(v.Type().Key()) { + return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type()) + } + if x := v.MapIndex(index); x.IsValid() { + v = x + } else { + v = reflect.Zero(v.Type().Elem()) + } + default: + return nil, fmt.Errorf("can't index item of type %s", v.Type()) + } + } + return v.Interface(), nil +} + +// Length + +// length returns the length of the item, with an error if it has no defined length. +func length(item interface{}) (int, error) { + v, isNil := indirect(reflect.ValueOf(item)) + if isNil { + return 0, fmt.Errorf("len of nil pointer") + } + switch v.Kind() { + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String: + return v.Len(), nil + } + return 0, fmt.Errorf("len of type %s", v.Type()) +} + +// Function invocation + +// call returns the result of evaluating the first argument as a function. +// The function must return 1 result, or 2 results, the second of which is an error. +func call(fn interface{}, args ...interface{}) (interface{}, error) { + v := reflect.ValueOf(fn) + typ := v.Type() + if typ.Kind() != reflect.Func { + return nil, fmt.Errorf("non-function of type %s", typ) + } + if !goodFunc(typ) { + return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut()) + } + numIn := typ.NumIn() + var dddType reflect.Type + if typ.IsVariadic() { + if len(args) < numIn-1 { + return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1) + } + dddType = typ.In(numIn - 1).Elem() + } else { + if len(args) != numIn { + return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn) + } + } + argv := make([]reflect.Value, len(args)) + for i, arg := range args { + value := reflect.ValueOf(arg) + // Compute the expected type. Clumsy because of variadics. + var argType reflect.Type + if !typ.IsVariadic() || i < numIn-1 { + argType = typ.In(i) + } else { + argType = dddType + } + if !value.IsValid() && canBeNil(argType) { + value = reflect.Zero(argType) + } + if !value.Type().AssignableTo(argType) { + return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType) + } + argv[i] = value + } + result := v.Call(argv) + if len(result) == 2 && !result[1].IsNil() { + return result[0].Interface(), result[1].Interface().(error) + } + return result[0].Interface(), nil +} + +// Boolean logic. + +func truth(a interface{}) bool { + t, _ := isTrue(reflect.ValueOf(a)) + return t +} + +// and computes the Boolean AND of its arguments, returning +// the first false argument it encounters, or the last argument. +func and(arg0 interface{}, args ...interface{}) interface{} { + if !truth(arg0) { + return arg0 + } + for i := range args { + arg0 = args[i] + if !truth(arg0) { + break + } + } + return arg0 +} + +// or computes the Boolean OR of its arguments, returning +// the first true argument it encounters, or the last argument. +func or(arg0 interface{}, args ...interface{}) interface{} { + if truth(arg0) { + return arg0 + } + for i := range args { + arg0 = args[i] + if truth(arg0) { + break + } + } + return arg0 +} + +// not returns the Boolean negation of its argument. +func not(arg interface{}) (truth bool) { + truth, _ = isTrue(reflect.ValueOf(arg)) + return !truth +} + +// Comparison. + +// TODO: Perhaps allow comparison between signed and unsigned integers. + +var ( + errBadComparisonType = errors.New("invalid type for comparison") + errBadComparison = errors.New("incompatible types for comparison") + errNoComparison = errors.New("missing argument for comparison") +) + +type kind int + +const ( + invalidKind kind = iota + boolKind + complexKind + intKind + floatKind + integerKind + stringKind + uintKind +) + +func basicKind(v reflect.Value) (kind, error) { + switch v.Kind() { + case reflect.Bool: + return boolKind, nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return intKind, nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return uintKind, nil + case reflect.Float32, reflect.Float64: + return floatKind, nil + case reflect.Complex64, reflect.Complex128: + return complexKind, nil + case reflect.String: + return stringKind, nil + } + return invalidKind, errBadComparisonType +} + +// eq evaluates the comparison a == b || a == c || ... +func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) { + v1 := reflect.ValueOf(arg1) + k1, err := basicKind(v1) + if err != nil { + return false, err + } + if len(arg2) == 0 { + return false, errNoComparison + } + for _, arg := range arg2 { + v2 := reflect.ValueOf(arg) + k2, err := basicKind(v2) + if err != nil { + return false, err + } + truth := false + if k1 != k2 { + // Special case: Can compare integer values regardless of type's sign. + switch { + case k1 == intKind && k2 == uintKind: + truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint() + case k1 == uintKind && k2 == intKind: + truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int()) + default: + return false, errBadComparison + } + } else { + switch k1 { + case boolKind: + truth = v1.Bool() == v2.Bool() + case complexKind: + truth = v1.Complex() == v2.Complex() + case floatKind: + truth = v1.Float() == v2.Float() + case intKind: + truth = v1.Int() == v2.Int() + case stringKind: + truth = v1.String() == v2.String() + case uintKind: + truth = v1.Uint() == v2.Uint() + default: + panic("invalid kind") + } + } + if truth { + return true, nil + } + } + return false, nil +} + +// ne evaluates the comparison a != b. +func ne(arg1, arg2 interface{}) (bool, error) { + // != is the inverse of ==. + equal, err := eq(arg1, arg2) + return !equal, err +} + +// lt evaluates the comparison a < b. +func lt(arg1, arg2 interface{}) (bool, error) { + v1 := reflect.ValueOf(arg1) + k1, err := basicKind(v1) + if err != nil { + return false, err + } + v2 := reflect.ValueOf(arg2) + k2, err := basicKind(v2) + if err != nil { + return false, err + } + truth := false + if k1 != k2 { + // Special case: Can compare integer values regardless of type's sign. + switch { + case k1 == intKind && k2 == uintKind: + truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint() + case k1 == uintKind && k2 == intKind: + truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int()) + default: + return false, errBadComparison + } + } else { + switch k1 { + case boolKind, complexKind: + return false, errBadComparisonType + case floatKind: + truth = v1.Float() < v2.Float() + case intKind: + truth = v1.Int() < v2.Int() + case stringKind: + truth = v1.String() < v2.String() + case uintKind: + truth = v1.Uint() < v2.Uint() + default: + panic("invalid kind") + } + } + return truth, nil +} + +// le evaluates the comparison <= b. +func le(arg1, arg2 interface{}) (bool, error) { + // <= is < or ==. + lessThan, err := lt(arg1, arg2) + if lessThan || err != nil { + return lessThan, err + } + return eq(arg1, arg2) +} + +// gt evaluates the comparison a > b. +func gt(arg1, arg2 interface{}) (bool, error) { + // > is the inverse of <=. + lessOrEqual, err := le(arg1, arg2) + if err != nil { + return false, err + } + return !lessOrEqual, nil +} + +// ge evaluates the comparison a >= b. +func ge(arg1, arg2 interface{}) (bool, error) { + // >= is the inverse of <. + lessThan, err := lt(arg1, arg2) + if err != nil { + return false, err + } + return !lessThan, nil +} + +// HTML escaping. + +var ( + htmlQuot = []byte(""") // shorter than """ + htmlApos = []byte("'") // shorter than "'" and apos was not in HTML until HTML5 + htmlAmp = []byte("&") + htmlLt = []byte("<") + htmlGt = []byte(">") +) + +// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b. +func HTMLEscape(w io.Writer, b []byte) { + last := 0 + for i, c := range b { + var html []byte + switch c { + case '"': + html = htmlQuot + case '\'': + html = htmlApos + case '&': + html = htmlAmp + case '<': + html = htmlLt + case '>': + html = htmlGt + default: + continue + } + w.Write(b[last:i]) + w.Write(html) + last = i + 1 + } + w.Write(b[last:]) +} + +// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s. +func HTMLEscapeString(s string) string { + // Avoid allocation if we can. + if strings.IndexAny(s, `'"&<>`) < 0 { + return s + } + var b bytes.Buffer + HTMLEscape(&b, []byte(s)) + return b.String() +} + +// HTMLEscaper returns the escaped HTML equivalent of the textual +// representation of its arguments. +func HTMLEscaper(args ...interface{}) string { + return HTMLEscapeString(evalArgs(args)) +} + +// JavaScript escaping. + +var ( + jsLowUni = []byte(`\u00`) + hex = []byte("0123456789ABCDEF") + + jsBackslash = []byte(`\\`) + jsApos = []byte(`\'`) + jsQuot = []byte(`\"`) + jsLt = []byte(`\x3C`) + jsGt = []byte(`\x3E`) +) + +// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b. +func JSEscape(w io.Writer, b []byte) { + last := 0 + for i := 0; i < len(b); i++ { + c := b[i] + + if !jsIsSpecial(rune(c)) { + // fast path: nothing to do + continue + } + w.Write(b[last:i]) + + if c < utf8.RuneSelf { + // Quotes, slashes and angle brackets get quoted. + // Control characters get written as \u00XX. + switch c { + case '\\': + w.Write(jsBackslash) + case '\'': + w.Write(jsApos) + case '"': + w.Write(jsQuot) + case '<': + w.Write(jsLt) + case '>': + w.Write(jsGt) + default: + w.Write(jsLowUni) + t, b := c>>4, c&0x0f + w.Write(hex[t : t+1]) + w.Write(hex[b : b+1]) + } + } else { + // Unicode rune. + r, size := utf8.DecodeRune(b[i:]) + if unicode.IsPrint(r) { + w.Write(b[i : i+size]) + } else { + fmt.Fprintf(w, "\\u%04X", r) + } + i += size - 1 + } + last = i + 1 + } + w.Write(b[last:]) +} + +// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s. +func JSEscapeString(s string) string { + // Avoid allocation if we can. + if strings.IndexFunc(s, jsIsSpecial) < 0 { + return s + } + var b bytes.Buffer + JSEscape(&b, []byte(s)) + return b.String() +} + +func jsIsSpecial(r rune) bool { + switch r { + case '\\', '\'', '"', '<', '>': + return true + } + return r < ' ' || utf8.RuneSelf <= r +} + +// JSEscaper returns the escaped JavaScript equivalent of the textual +// representation of its arguments. +func JSEscaper(args ...interface{}) string { + return JSEscapeString(evalArgs(args)) +} + +// URLQueryEscaper returns the escaped value of the textual representation of +// its arguments in a form suitable for embedding in a URL query. +func URLQueryEscaper(args ...interface{}) string { + return url.QueryEscape(evalArgs(args)) +} + +// evalArgs formats the list of arguments into a string. It is therefore equivalent to +// fmt.Sprint(args...) +// except that each argument is indirected (if a pointer), as required, +// using the same rules as the default string evaluation during template +// execution. +func evalArgs(args []interface{}) string { + ok := false + var s string + // Fast path for simple common case. + if len(args) == 1 { + s, ok = args[0].(string) + } + if !ok { + for i, arg := range args { + a, ok := printableValue(reflect.ValueOf(arg)) + if ok { + args[i] = a + } // else left fmt do its thing + } + s = fmt.Sprint(args...) + } + return s +} diff --git a/vendor/github.com/alecthomas/template/helper.go b/vendor/github.com/alecthomas/template/helper.go new file mode 100644 index 0000000..3636fb5 --- /dev/null +++ b/vendor/github.com/alecthomas/template/helper.go @@ -0,0 +1,108 @@ +// Copyright 2011 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. + +// Helper functions to make constructing templates easier. + +package template + +import ( + "fmt" + "io/ioutil" + "path/filepath" +) + +// Functions and methods to parse templates. + +// Must is a helper that wraps a call to a function returning (*Template, error) +// and panics if the error is non-nil. It is intended for use in variable +// initializations such as +// var t = template.Must(template.New("name").Parse("text")) +func Must(t *Template, err error) *Template { + if err != nil { + panic(err) + } + return t +} + +// ParseFiles creates a new Template and parses the template definitions from +// the named files. The returned template's name will have the (base) name and +// (parsed) contents of the first file. There must be at least one file. +// If an error occurs, parsing stops and the returned *Template is nil. +func ParseFiles(filenames ...string) (*Template, error) { + return parseFiles(nil, filenames...) +} + +// ParseFiles parses the named files and associates the resulting templates with +// t. If an error occurs, parsing stops and the returned template is nil; +// otherwise it is t. There must be at least one file. +func (t *Template) ParseFiles(filenames ...string) (*Template, error) { + return parseFiles(t, filenames...) +} + +// parseFiles is the helper for the method and function. If the argument +// template is nil, it is created from the first file. +func parseFiles(t *Template, filenames ...string) (*Template, error) { + if len(filenames) == 0 { + // Not really a problem, but be consistent. + return nil, fmt.Errorf("template: no files named in call to ParseFiles") + } + for _, filename := range filenames { + b, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + s := string(b) + name := filepath.Base(filename) + // First template becomes return value if not already defined, + // and we use that one for subsequent New calls to associate + // all the templates together. Also, if this file has the same name + // as t, this file becomes the contents of t, so + // t, err := New(name).Funcs(xxx).ParseFiles(name) + // works. Otherwise we create a new template associated with t. + var tmpl *Template + if t == nil { + t = New(name) + } + if name == t.Name() { + tmpl = t + } else { + tmpl = t.New(name) + } + _, err = tmpl.Parse(s) + if err != nil { + return nil, err + } + } + return t, nil +} + +// ParseGlob creates a new Template and parses the template definitions from the +// files identified by the pattern, which must match at least one file. The +// returned template will have the (base) name and (parsed) contents of the +// first file matched by the pattern. ParseGlob is equivalent to calling +// ParseFiles with the list of files matched by the pattern. +func ParseGlob(pattern string) (*Template, error) { + return parseGlob(nil, pattern) +} + +// ParseGlob parses the template definitions in the files identified by the +// pattern and associates the resulting templates with t. The pattern is +// processed by filepath.Glob and must match at least one file. ParseGlob is +// equivalent to calling t.ParseFiles with the list of files matched by the +// pattern. +func (t *Template) ParseGlob(pattern string) (*Template, error) { + return parseGlob(t, pattern) +} + +// parseGlob is the implementation of the function and method ParseGlob. +func parseGlob(t *Template, pattern string) (*Template, error) { + filenames, err := filepath.Glob(pattern) + if err != nil { + return nil, err + } + if len(filenames) == 0 { + return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern) + } + return parseFiles(t, filenames...) +} diff --git a/vendor/github.com/alecthomas/template/parse/lex.go b/vendor/github.com/alecthomas/template/parse/lex.go new file mode 100644 index 0000000..55f1c05 --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/lex.go @@ -0,0 +1,556 @@ +// Copyright 2011 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. + +package parse + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" +) + +// item represents a token or text string returned from the scanner. +type item struct { + typ itemType // The type of this item. + pos Pos // The starting position, in bytes, of this item in the input string. + val string // The value of this item. +} + +func (i item) String() string { + switch { + case i.typ == itemEOF: + return "EOF" + case i.typ == itemError: + return i.val + case i.typ > itemKeyword: + return fmt.Sprintf("<%s>", i.val) + case len(i.val) > 10: + return fmt.Sprintf("%.10q...", i.val) + } + return fmt.Sprintf("%q", i.val) +} + +// itemType identifies the type of lex items. +type itemType int + +const ( + itemError itemType = iota // error occurred; value is text of error + itemBool // boolean constant + itemChar // printable ASCII character; grab bag for comma etc. + itemCharConstant // character constant + itemComplex // complex constant (1+2i); imaginary is just a number + itemColonEquals // colon-equals (':=') introducing a declaration + itemEOF + itemField // alphanumeric identifier starting with '.' + itemIdentifier // alphanumeric identifier not starting with '.' + itemLeftDelim // left action delimiter + itemLeftParen // '(' inside action + itemNumber // simple number, including imaginary + itemPipe // pipe symbol + itemRawString // raw quoted string (includes quotes) + itemRightDelim // right action delimiter + itemElideNewline // elide newline after right delim + itemRightParen // ')' inside action + itemSpace // run of spaces separating arguments + itemString // quoted string (includes quotes) + itemText // plain text + itemVariable // variable starting with '$', such as '$' or '$1' or '$hello' + // Keywords appear after all the rest. + itemKeyword // used only to delimit the keywords + itemDot // the cursor, spelled '.' + itemDefine // define keyword + itemElse // else keyword + itemEnd // end keyword + itemIf // if keyword + itemNil // the untyped nil constant, easiest to treat as a keyword + itemRange // range keyword + itemTemplate // template keyword + itemWith // with keyword +) + +var key = map[string]itemType{ + ".": itemDot, + "define": itemDefine, + "else": itemElse, + "end": itemEnd, + "if": itemIf, + "range": itemRange, + "nil": itemNil, + "template": itemTemplate, + "with": itemWith, +} + +const eof = -1 + +// stateFn represents the state of the scanner as a function that returns the next state. +type stateFn func(*lexer) stateFn + +// lexer holds the state of the scanner. +type lexer struct { + name string // the name of the input; used only for error reports + input string // the string being scanned + leftDelim string // start of action + rightDelim string // end of action + state stateFn // the next lexing function to enter + pos Pos // current position in the input + start Pos // start position of this item + width Pos // width of last rune read from input + lastPos Pos // position of most recent item returned by nextItem + items chan item // channel of scanned items + parenDepth int // nesting depth of ( ) exprs +} + +// next returns the next rune in the input. +func (l *lexer) next() rune { + if int(l.pos) >= len(l.input) { + l.width = 0 + return eof + } + r, w := utf8.DecodeRuneInString(l.input[l.pos:]) + l.width = Pos(w) + l.pos += l.width + return r +} + +// peek returns but does not consume the next rune in the input. +func (l *lexer) peek() rune { + r := l.next() + l.backup() + return r +} + +// backup steps back one rune. Can only be called once per call of next. +func (l *lexer) backup() { + l.pos -= l.width +} + +// emit passes an item back to the client. +func (l *lexer) emit(t itemType) { + l.items <- item{t, l.start, l.input[l.start:l.pos]} + l.start = l.pos +} + +// ignore skips over the pending input before this point. +func (l *lexer) ignore() { + l.start = l.pos +} + +// accept consumes the next rune if it's from the valid set. +func (l *lexer) accept(valid string) bool { + if strings.IndexRune(valid, l.next()) >= 0 { + return true + } + l.backup() + return false +} + +// acceptRun consumes a run of runes from the valid set. +func (l *lexer) acceptRun(valid string) { + for strings.IndexRune(valid, l.next()) >= 0 { + } + l.backup() +} + +// lineNumber reports which line we're on, based on the position of +// the previous item returned by nextItem. Doing it this way +// means we don't have to worry about peek double counting. +func (l *lexer) lineNumber() int { + return 1 + strings.Count(l.input[:l.lastPos], "\n") +} + +// errorf returns an error token and terminates the scan by passing +// back a nil pointer that will be the next state, terminating l.nextItem. +func (l *lexer) errorf(format string, args ...interface{}) stateFn { + l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)} + return nil +} + +// nextItem returns the next item from the input. +func (l *lexer) nextItem() item { + item := <-l.items + l.lastPos = item.pos + return item +} + +// lex creates a new scanner for the input string. +func lex(name, input, left, right string) *lexer { + if left == "" { + left = leftDelim + } + if right == "" { + right = rightDelim + } + l := &lexer{ + name: name, + input: input, + leftDelim: left, + rightDelim: right, + items: make(chan item), + } + go l.run() + return l +} + +// run runs the state machine for the lexer. +func (l *lexer) run() { + for l.state = lexText; l.state != nil; { + l.state = l.state(l) + } +} + +// state functions + +const ( + leftDelim = "{{" + rightDelim = "}}" + leftComment = "/*" + rightComment = "*/" +) + +// lexText scans until an opening action delimiter, "{{". +func lexText(l *lexer) stateFn { + for { + if strings.HasPrefix(l.input[l.pos:], l.leftDelim) { + if l.pos > l.start { + l.emit(itemText) + } + return lexLeftDelim + } + if l.next() == eof { + break + } + } + // Correctly reached EOF. + if l.pos > l.start { + l.emit(itemText) + } + l.emit(itemEOF) + return nil +} + +// lexLeftDelim scans the left delimiter, which is known to be present. +func lexLeftDelim(l *lexer) stateFn { + l.pos += Pos(len(l.leftDelim)) + if strings.HasPrefix(l.input[l.pos:], leftComment) { + return lexComment + } + l.emit(itemLeftDelim) + l.parenDepth = 0 + return lexInsideAction +} + +// lexComment scans a comment. The left comment marker is known to be present. +func lexComment(l *lexer) stateFn { + l.pos += Pos(len(leftComment)) + i := strings.Index(l.input[l.pos:], rightComment) + if i < 0 { + return l.errorf("unclosed comment") + } + l.pos += Pos(i + len(rightComment)) + if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) { + return l.errorf("comment ends before closing delimiter") + + } + l.pos += Pos(len(l.rightDelim)) + l.ignore() + return lexText +} + +// lexRightDelim scans the right delimiter, which is known to be present. +func lexRightDelim(l *lexer) stateFn { + l.pos += Pos(len(l.rightDelim)) + l.emit(itemRightDelim) + if l.peek() == '\\' { + l.pos++ + l.emit(itemElideNewline) + } + return lexText +} + +// lexInsideAction scans the elements inside action delimiters. +func lexInsideAction(l *lexer) stateFn { + // Either number, quoted string, or identifier. + // Spaces separate arguments; runs of spaces turn into itemSpace. + // Pipe symbols separate and are emitted. + if strings.HasPrefix(l.input[l.pos:], l.rightDelim+"\\") || strings.HasPrefix(l.input[l.pos:], l.rightDelim) { + if l.parenDepth == 0 { + return lexRightDelim + } + return l.errorf("unclosed left paren") + } + switch r := l.next(); { + case r == eof || isEndOfLine(r): + return l.errorf("unclosed action") + case isSpace(r): + return lexSpace + case r == ':': + if l.next() != '=' { + return l.errorf("expected :=") + } + l.emit(itemColonEquals) + case r == '|': + l.emit(itemPipe) + case r == '"': + return lexQuote + case r == '`': + return lexRawQuote + case r == '$': + return lexVariable + case r == '\'': + return lexChar + case r == '.': + // special look-ahead for ".field" so we don't break l.backup(). + if l.pos < Pos(len(l.input)) { + r := l.input[l.pos] + if r < '0' || '9' < r { + return lexField + } + } + fallthrough // '.' can start a number. + case r == '+' || r == '-' || ('0' <= r && r <= '9'): + l.backup() + return lexNumber + case isAlphaNumeric(r): + l.backup() + return lexIdentifier + case r == '(': + l.emit(itemLeftParen) + l.parenDepth++ + return lexInsideAction + case r == ')': + l.emit(itemRightParen) + l.parenDepth-- + if l.parenDepth < 0 { + return l.errorf("unexpected right paren %#U", r) + } + return lexInsideAction + case r <= unicode.MaxASCII && unicode.IsPrint(r): + l.emit(itemChar) + return lexInsideAction + default: + return l.errorf("unrecognized character in action: %#U", r) + } + return lexInsideAction +} + +// lexSpace scans a run of space characters. +// One space has already been seen. +func lexSpace(l *lexer) stateFn { + for isSpace(l.peek()) { + l.next() + } + l.emit(itemSpace) + return lexInsideAction +} + +// lexIdentifier scans an alphanumeric. +func lexIdentifier(l *lexer) stateFn { +Loop: + for { + switch r := l.next(); { + case isAlphaNumeric(r): + // absorb. + default: + l.backup() + word := l.input[l.start:l.pos] + if !l.atTerminator() { + return l.errorf("bad character %#U", r) + } + switch { + case key[word] > itemKeyword: + l.emit(key[word]) + case word[0] == '.': + l.emit(itemField) + case word == "true", word == "false": + l.emit(itemBool) + default: + l.emit(itemIdentifier) + } + break Loop + } + } + return lexInsideAction +} + +// lexField scans a field: .Alphanumeric. +// The . has been scanned. +func lexField(l *lexer) stateFn { + return lexFieldOrVariable(l, itemField) +} + +// lexVariable scans a Variable: $Alphanumeric. +// The $ has been scanned. +func lexVariable(l *lexer) stateFn { + if l.atTerminator() { // Nothing interesting follows -> "$". + l.emit(itemVariable) + return lexInsideAction + } + return lexFieldOrVariable(l, itemVariable) +} + +// lexVariable scans a field or variable: [.$]Alphanumeric. +// The . or $ has been scanned. +func lexFieldOrVariable(l *lexer, typ itemType) stateFn { + if l.atTerminator() { // Nothing interesting follows -> "." or "$". + if typ == itemVariable { + l.emit(itemVariable) + } else { + l.emit(itemDot) + } + return lexInsideAction + } + var r rune + for { + r = l.next() + if !isAlphaNumeric(r) { + l.backup() + break + } + } + if !l.atTerminator() { + return l.errorf("bad character %#U", r) + } + l.emit(typ) + return lexInsideAction +} + +// atTerminator reports whether the input is at valid termination character to +// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases +// like "$x+2" not being acceptable without a space, in case we decide one +// day to implement arithmetic. +func (l *lexer) atTerminator() bool { + r := l.peek() + if isSpace(r) || isEndOfLine(r) { + return true + } + switch r { + case eof, '.', ',', '|', ':', ')', '(': + return true + } + // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will + // succeed but should fail) but only in extremely rare cases caused by willfully + // bad choice of delimiter. + if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r { + return true + } + return false +} + +// lexChar scans a character constant. The initial quote is already +// scanned. Syntax checking is done by the parser. +func lexChar(l *lexer) stateFn { +Loop: + for { + switch l.next() { + case '\\': + if r := l.next(); r != eof && r != '\n' { + break + } + fallthrough + case eof, '\n': + return l.errorf("unterminated character constant") + case '\'': + break Loop + } + } + l.emit(itemCharConstant) + return lexInsideAction +} + +// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This +// isn't a perfect number scanner - for instance it accepts "." and "0x0.2" +// and "089" - but when it's wrong the input is invalid and the parser (via +// strconv) will notice. +func lexNumber(l *lexer) stateFn { + if !l.scanNumber() { + return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) + } + if sign := l.peek(); sign == '+' || sign == '-' { + // Complex: 1+2i. No spaces, must end in 'i'. + if !l.scanNumber() || l.input[l.pos-1] != 'i' { + return l.errorf("bad number syntax: %q", l.input[l.start:l.pos]) + } + l.emit(itemComplex) + } else { + l.emit(itemNumber) + } + return lexInsideAction +} + +func (l *lexer) scanNumber() bool { + // Optional leading sign. + l.accept("+-") + // Is it hex? + digits := "0123456789" + if l.accept("0") && l.accept("xX") { + digits = "0123456789abcdefABCDEF" + } + l.acceptRun(digits) + if l.accept(".") { + l.acceptRun(digits) + } + if l.accept("eE") { + l.accept("+-") + l.acceptRun("0123456789") + } + // Is it imaginary? + l.accept("i") + // Next thing mustn't be alphanumeric. + if isAlphaNumeric(l.peek()) { + l.next() + return false + } + return true +} + +// lexQuote scans a quoted string. +func lexQuote(l *lexer) stateFn { +Loop: + for { + switch l.next() { + case '\\': + if r := l.next(); r != eof && r != '\n' { + break + } + fallthrough + case eof, '\n': + return l.errorf("unterminated quoted string") + case '"': + break Loop + } + } + l.emit(itemString) + return lexInsideAction +} + +// lexRawQuote scans a raw quoted string. +func lexRawQuote(l *lexer) stateFn { +Loop: + for { + switch l.next() { + case eof, '\n': + return l.errorf("unterminated raw quoted string") + case '`': + break Loop + } + } + l.emit(itemRawString) + return lexInsideAction +} + +// isSpace reports whether r is a space character. +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +// isEndOfLine reports whether r is an end-of-line character. +func isEndOfLine(r rune) bool { + return r == '\r' || r == '\n' +} + +// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore. +func isAlphaNumeric(r rune) bool { + return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r) +} diff --git a/vendor/github.com/alecthomas/template/parse/node.go b/vendor/github.com/alecthomas/template/parse/node.go new file mode 100644 index 0000000..55c37f6 --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/node.go @@ -0,0 +1,834 @@ +// Copyright 2011 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. + +// Parse nodes. + +package parse + +import ( + "bytes" + "fmt" + "strconv" + "strings" +) + +var textFormat = "%s" // Changed to "%q" in tests for better error messages. + +// A Node is an element in the parse tree. The interface is trivial. +// The interface contains an unexported method so that only +// types local to this package can satisfy it. +type Node interface { + Type() NodeType + String() string + // Copy does a deep copy of the Node and all its components. + // To avoid type assertions, some XxxNodes also have specialized + // CopyXxx methods that return *XxxNode. + Copy() Node + Position() Pos // byte position of start of node in full original input string + // tree returns the containing *Tree. + // It is unexported so all implementations of Node are in this package. + tree() *Tree +} + +// NodeType identifies the type of a parse tree node. +type NodeType int + +// Pos represents a byte position in the original input text from which +// this template was parsed. +type Pos int + +func (p Pos) Position() Pos { + return p +} + +// Type returns itself and provides an easy default implementation +// for embedding in a Node. Embedded in all non-trivial Nodes. +func (t NodeType) Type() NodeType { + return t +} + +const ( + NodeText NodeType = iota // Plain text. + NodeAction // A non-control action such as a field evaluation. + NodeBool // A boolean constant. + NodeChain // A sequence of field accesses. + NodeCommand // An element of a pipeline. + NodeDot // The cursor, dot. + nodeElse // An else action. Not added to tree. + nodeEnd // An end action. Not added to tree. + NodeField // A field or method name. + NodeIdentifier // An identifier; always a function name. + NodeIf // An if action. + NodeList // A list of Nodes. + NodeNil // An untyped nil constant. + NodeNumber // A numerical constant. + NodePipe // A pipeline of commands. + NodeRange // A range action. + NodeString // A string constant. + NodeTemplate // A template invocation action. + NodeVariable // A $ variable. + NodeWith // A with action. +) + +// Nodes. + +// ListNode holds a sequence of nodes. +type ListNode struct { + NodeType + Pos + tr *Tree + Nodes []Node // The element nodes in lexical order. +} + +func (t *Tree) newList(pos Pos) *ListNode { + return &ListNode{tr: t, NodeType: NodeList, Pos: pos} +} + +func (l *ListNode) append(n Node) { + l.Nodes = append(l.Nodes, n) +} + +func (l *ListNode) tree() *Tree { + return l.tr +} + +func (l *ListNode) String() string { + b := new(bytes.Buffer) + for _, n := range l.Nodes { + fmt.Fprint(b, n) + } + return b.String() +} + +func (l *ListNode) CopyList() *ListNode { + if l == nil { + return l + } + n := l.tr.newList(l.Pos) + for _, elem := range l.Nodes { + n.append(elem.Copy()) + } + return n +} + +func (l *ListNode) Copy() Node { + return l.CopyList() +} + +// TextNode holds plain text. +type TextNode struct { + NodeType + Pos + tr *Tree + Text []byte // The text; may span newlines. +} + +func (t *Tree) newText(pos Pos, text string) *TextNode { + return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)} +} + +func (t *TextNode) String() string { + return fmt.Sprintf(textFormat, t.Text) +} + +func (t *TextNode) tree() *Tree { + return t.tr +} + +func (t *TextNode) Copy() Node { + return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)} +} + +// PipeNode holds a pipeline with optional declaration +type PipeNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Decl []*VariableNode // Variable declarations in lexical order. + Cmds []*CommandNode // The commands in lexical order. +} + +func (t *Tree) newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode { + return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: decl} +} + +func (p *PipeNode) append(command *CommandNode) { + p.Cmds = append(p.Cmds, command) +} + +func (p *PipeNode) String() string { + s := "" + if len(p.Decl) > 0 { + for i, v := range p.Decl { + if i > 0 { + s += ", " + } + s += v.String() + } + s += " := " + } + for i, c := range p.Cmds { + if i > 0 { + s += " | " + } + s += c.String() + } + return s +} + +func (p *PipeNode) tree() *Tree { + return p.tr +} + +func (p *PipeNode) CopyPipe() *PipeNode { + if p == nil { + return p + } + var decl []*VariableNode + for _, d := range p.Decl { + decl = append(decl, d.Copy().(*VariableNode)) + } + n := p.tr.newPipeline(p.Pos, p.Line, decl) + for _, c := range p.Cmds { + n.append(c.Copy().(*CommandNode)) + } + return n +} + +func (p *PipeNode) Copy() Node { + return p.CopyPipe() +} + +// ActionNode holds an action (something bounded by delimiters). +// Control actions have their own nodes; ActionNode represents simple +// ones such as field evaluations and parenthesized pipelines. +type ActionNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Pipe *PipeNode // The pipeline in the action. +} + +func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode { + return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe} +} + +func (a *ActionNode) String() string { + return fmt.Sprintf("{{%s}}", a.Pipe) + +} + +func (a *ActionNode) tree() *Tree { + return a.tr +} + +func (a *ActionNode) Copy() Node { + return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe()) + +} + +// CommandNode holds a command (a pipeline inside an evaluating action). +type CommandNode struct { + NodeType + Pos + tr *Tree + Args []Node // Arguments in lexical order: Identifier, field, or constant. +} + +func (t *Tree) newCommand(pos Pos) *CommandNode { + return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos} +} + +func (c *CommandNode) append(arg Node) { + c.Args = append(c.Args, arg) +} + +func (c *CommandNode) String() string { + s := "" + for i, arg := range c.Args { + if i > 0 { + s += " " + } + if arg, ok := arg.(*PipeNode); ok { + s += "(" + arg.String() + ")" + continue + } + s += arg.String() + } + return s +} + +func (c *CommandNode) tree() *Tree { + return c.tr +} + +func (c *CommandNode) Copy() Node { + if c == nil { + return c + } + n := c.tr.newCommand(c.Pos) + for _, c := range c.Args { + n.append(c.Copy()) + } + return n +} + +// IdentifierNode holds an identifier. +type IdentifierNode struct { + NodeType + Pos + tr *Tree + Ident string // The identifier's name. +} + +// NewIdentifier returns a new IdentifierNode with the given identifier name. +func NewIdentifier(ident string) *IdentifierNode { + return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident} +} + +// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature. +// Chained for convenience. +// TODO: fix one day? +func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode { + i.Pos = pos + return i +} + +// SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature. +// Chained for convenience. +// TODO: fix one day? +func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode { + i.tr = t + return i +} + +func (i *IdentifierNode) String() string { + return i.Ident +} + +func (i *IdentifierNode) tree() *Tree { + return i.tr +} + +func (i *IdentifierNode) Copy() Node { + return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos) +} + +// VariableNode holds a list of variable names, possibly with chained field +// accesses. The dollar sign is part of the (first) name. +type VariableNode struct { + NodeType + Pos + tr *Tree + Ident []string // Variable name and fields in lexical order. +} + +func (t *Tree) newVariable(pos Pos, ident string) *VariableNode { + return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")} +} + +func (v *VariableNode) String() string { + s := "" + for i, id := range v.Ident { + if i > 0 { + s += "." + } + s += id + } + return s +} + +func (v *VariableNode) tree() *Tree { + return v.tr +} + +func (v *VariableNode) Copy() Node { + return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)} +} + +// DotNode holds the special identifier '.'. +type DotNode struct { + NodeType + Pos + tr *Tree +} + +func (t *Tree) newDot(pos Pos) *DotNode { + return &DotNode{tr: t, NodeType: NodeDot, Pos: pos} +} + +func (d *DotNode) Type() NodeType { + // Override method on embedded NodeType for API compatibility. + // TODO: Not really a problem; could change API without effect but + // api tool complains. + return NodeDot +} + +func (d *DotNode) String() string { + return "." +} + +func (d *DotNode) tree() *Tree { + return d.tr +} + +func (d *DotNode) Copy() Node { + return d.tr.newDot(d.Pos) +} + +// NilNode holds the special identifier 'nil' representing an untyped nil constant. +type NilNode struct { + NodeType + Pos + tr *Tree +} + +func (t *Tree) newNil(pos Pos) *NilNode { + return &NilNode{tr: t, NodeType: NodeNil, Pos: pos} +} + +func (n *NilNode) Type() NodeType { + // Override method on embedded NodeType for API compatibility. + // TODO: Not really a problem; could change API without effect but + // api tool complains. + return NodeNil +} + +func (n *NilNode) String() string { + return "nil" +} + +func (n *NilNode) tree() *Tree { + return n.tr +} + +func (n *NilNode) Copy() Node { + return n.tr.newNil(n.Pos) +} + +// FieldNode holds a field (identifier starting with '.'). +// The names may be chained ('.x.y'). +// The period is dropped from each ident. +type FieldNode struct { + NodeType + Pos + tr *Tree + Ident []string // The identifiers in lexical order. +} + +func (t *Tree) newField(pos Pos, ident string) *FieldNode { + return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period +} + +func (f *FieldNode) String() string { + s := "" + for _, id := range f.Ident { + s += "." + id + } + return s +} + +func (f *FieldNode) tree() *Tree { + return f.tr +} + +func (f *FieldNode) Copy() Node { + return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)} +} + +// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.'). +// The names may be chained ('.x.y'). +// The periods are dropped from each ident. +type ChainNode struct { + NodeType + Pos + tr *Tree + Node Node + Field []string // The identifiers in lexical order. +} + +func (t *Tree) newChain(pos Pos, node Node) *ChainNode { + return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node} +} + +// Add adds the named field (which should start with a period) to the end of the chain. +func (c *ChainNode) Add(field string) { + if len(field) == 0 || field[0] != '.' { + panic("no dot in field") + } + field = field[1:] // Remove leading dot. + if field == "" { + panic("empty field") + } + c.Field = append(c.Field, field) +} + +func (c *ChainNode) String() string { + s := c.Node.String() + if _, ok := c.Node.(*PipeNode); ok { + s = "(" + s + ")" + } + for _, field := range c.Field { + s += "." + field + } + return s +} + +func (c *ChainNode) tree() *Tree { + return c.tr +} + +func (c *ChainNode) Copy() Node { + return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)} +} + +// BoolNode holds a boolean constant. +type BoolNode struct { + NodeType + Pos + tr *Tree + True bool // The value of the boolean constant. +} + +func (t *Tree) newBool(pos Pos, true bool) *BoolNode { + return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true} +} + +func (b *BoolNode) String() string { + if b.True { + return "true" + } + return "false" +} + +func (b *BoolNode) tree() *Tree { + return b.tr +} + +func (b *BoolNode) Copy() Node { + return b.tr.newBool(b.Pos, b.True) +} + +// NumberNode holds a number: signed or unsigned integer, float, or complex. +// The value is parsed and stored under all the types that can represent the value. +// This simulates in a small amount of code the behavior of Go's ideal constants. +type NumberNode struct { + NodeType + Pos + tr *Tree + IsInt bool // Number has an integral value. + IsUint bool // Number has an unsigned integral value. + IsFloat bool // Number has a floating-point value. + IsComplex bool // Number is complex. + Int64 int64 // The signed integer value. + Uint64 uint64 // The unsigned integer value. + Float64 float64 // The floating-point value. + Complex128 complex128 // The complex value. + Text string // The original textual representation from the input. +} + +func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) { + n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text} + switch typ { + case itemCharConstant: + rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0]) + if err != nil { + return nil, err + } + if tail != "'" { + return nil, fmt.Errorf("malformed character constant: %s", text) + } + n.Int64 = int64(rune) + n.IsInt = true + n.Uint64 = uint64(rune) + n.IsUint = true + n.Float64 = float64(rune) // odd but those are the rules. + n.IsFloat = true + return n, nil + case itemComplex: + // fmt.Sscan can parse the pair, so let it do the work. + if _, err := fmt.Sscan(text, &n.Complex128); err != nil { + return nil, err + } + n.IsComplex = true + n.simplifyComplex() + return n, nil + } + // Imaginary constants can only be complex unless they are zero. + if len(text) > 0 && text[len(text)-1] == 'i' { + f, err := strconv.ParseFloat(text[:len(text)-1], 64) + if err == nil { + n.IsComplex = true + n.Complex128 = complex(0, f) + n.simplifyComplex() + return n, nil + } + } + // Do integer test first so we get 0x123 etc. + u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below. + if err == nil { + n.IsUint = true + n.Uint64 = u + } + i, err := strconv.ParseInt(text, 0, 64) + if err == nil { + n.IsInt = true + n.Int64 = i + if i == 0 { + n.IsUint = true // in case of -0. + n.Uint64 = u + } + } + // If an integer extraction succeeded, promote the float. + if n.IsInt { + n.IsFloat = true + n.Float64 = float64(n.Int64) + } else if n.IsUint { + n.IsFloat = true + n.Float64 = float64(n.Uint64) + } else { + f, err := strconv.ParseFloat(text, 64) + if err == nil { + n.IsFloat = true + n.Float64 = f + // If a floating-point extraction succeeded, extract the int if needed. + if !n.IsInt && float64(int64(f)) == f { + n.IsInt = true + n.Int64 = int64(f) + } + if !n.IsUint && float64(uint64(f)) == f { + n.IsUint = true + n.Uint64 = uint64(f) + } + } + } + if !n.IsInt && !n.IsUint && !n.IsFloat { + return nil, fmt.Errorf("illegal number syntax: %q", text) + } + return n, nil +} + +// simplifyComplex pulls out any other types that are represented by the complex number. +// These all require that the imaginary part be zero. +func (n *NumberNode) simplifyComplex() { + n.IsFloat = imag(n.Complex128) == 0 + if n.IsFloat { + n.Float64 = real(n.Complex128) + n.IsInt = float64(int64(n.Float64)) == n.Float64 + if n.IsInt { + n.Int64 = int64(n.Float64) + } + n.IsUint = float64(uint64(n.Float64)) == n.Float64 + if n.IsUint { + n.Uint64 = uint64(n.Float64) + } + } +} + +func (n *NumberNode) String() string { + return n.Text +} + +func (n *NumberNode) tree() *Tree { + return n.tr +} + +func (n *NumberNode) Copy() Node { + nn := new(NumberNode) + *nn = *n // Easy, fast, correct. + return nn +} + +// StringNode holds a string constant. The value has been "unquoted". +type StringNode struct { + NodeType + Pos + tr *Tree + Quoted string // The original text of the string, with quotes. + Text string // The string, after quote processing. +} + +func (t *Tree) newString(pos Pos, orig, text string) *StringNode { + return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text} +} + +func (s *StringNode) String() string { + return s.Quoted +} + +func (s *StringNode) tree() *Tree { + return s.tr +} + +func (s *StringNode) Copy() Node { + return s.tr.newString(s.Pos, s.Quoted, s.Text) +} + +// endNode represents an {{end}} action. +// It does not appear in the final parse tree. +type endNode struct { + NodeType + Pos + tr *Tree +} + +func (t *Tree) newEnd(pos Pos) *endNode { + return &endNode{tr: t, NodeType: nodeEnd, Pos: pos} +} + +func (e *endNode) String() string { + return "{{end}}" +} + +func (e *endNode) tree() *Tree { + return e.tr +} + +func (e *endNode) Copy() Node { + return e.tr.newEnd(e.Pos) +} + +// elseNode represents an {{else}} action. Does not appear in the final tree. +type elseNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) +} + +func (t *Tree) newElse(pos Pos, line int) *elseNode { + return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line} +} + +func (e *elseNode) Type() NodeType { + return nodeElse +} + +func (e *elseNode) String() string { + return "{{else}}" +} + +func (e *elseNode) tree() *Tree { + return e.tr +} + +func (e *elseNode) Copy() Node { + return e.tr.newElse(e.Pos, e.Line) +} + +// BranchNode is the common representation of if, range, and with. +type BranchNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Pipe *PipeNode // The pipeline to be evaluated. + List *ListNode // What to execute if the value is non-empty. + ElseList *ListNode // What to execute if the value is empty (nil if absent). +} + +func (b *BranchNode) String() string { + name := "" + switch b.NodeType { + case NodeIf: + name = "if" + case NodeRange: + name = "range" + case NodeWith: + name = "with" + default: + panic("unknown branch type") + } + if b.ElseList != nil { + return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList) + } + return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List) +} + +func (b *BranchNode) tree() *Tree { + return b.tr +} + +func (b *BranchNode) Copy() Node { + switch b.NodeType { + case NodeIf: + return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) + case NodeRange: + return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) + case NodeWith: + return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList) + default: + panic("unknown branch type") + } +} + +// IfNode represents an {{if}} action and its commands. +type IfNode struct { + BranchNode +} + +func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode { + return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} +} + +func (i *IfNode) Copy() Node { + return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList()) +} + +// RangeNode represents a {{range}} action and its commands. +type RangeNode struct { + BranchNode +} + +func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode { + return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} +} + +func (r *RangeNode) Copy() Node { + return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList()) +} + +// WithNode represents a {{with}} action and its commands. +type WithNode struct { + BranchNode +} + +func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode { + return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}} +} + +func (w *WithNode) Copy() Node { + return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList()) +} + +// TemplateNode represents a {{template}} action. +type TemplateNode struct { + NodeType + Pos + tr *Tree + Line int // The line number in the input (deprecated; kept for compatibility) + Name string // The name of the template (unquoted). + Pipe *PipeNode // The command to evaluate as dot for the template. +} + +func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode { + return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe} +} + +func (t *TemplateNode) String() string { + if t.Pipe == nil { + return fmt.Sprintf("{{template %q}}", t.Name) + } + return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe) +} + +func (t *TemplateNode) tree() *Tree { + return t.tr +} + +func (t *TemplateNode) Copy() Node { + return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe()) +} diff --git a/vendor/github.com/alecthomas/template/parse/parse.go b/vendor/github.com/alecthomas/template/parse/parse.go new file mode 100644 index 0000000..0d77ade --- /dev/null +++ b/vendor/github.com/alecthomas/template/parse/parse.go @@ -0,0 +1,700 @@ +// Copyright 2011 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. + +// Package parse builds parse trees for templates as defined by text/template +// and html/template. Clients should use those packages to construct templates +// rather than this one, which provides shared internal data structures not +// intended for general use. +package parse + +import ( + "bytes" + "fmt" + "runtime" + "strconv" + "strings" +) + +// Tree is the representation of a single parsed template. +type Tree struct { + Name string // name of the template represented by the tree. + ParseName string // name of the top-level template during parsing, for error messages. + Root *ListNode // top-level root of the tree. + text string // text parsed to create the template (or its parent) + // Parsing only; cleared after parse. + funcs []map[string]interface{} + lex *lexer + token [3]item // three-token lookahead for parser. + peekCount int + vars []string // variables defined at the moment. +} + +// Copy returns a copy of the Tree. Any parsing state is discarded. +func (t *Tree) Copy() *Tree { + if t == nil { + return nil + } + return &Tree{ + Name: t.Name, + ParseName: t.ParseName, + Root: t.Root.CopyList(), + text: t.text, + } +} + +// Parse returns a map from template name to parse.Tree, created by parsing the +// templates described in the argument string. The top-level template will be +// given the specified name. If an error is encountered, parsing stops and an +// empty map is returned with the error. +func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) { + treeSet = make(map[string]*Tree) + t := New(name) + t.text = text + _, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...) + return +} + +// next returns the next token. +func (t *Tree) next() item { + if t.peekCount > 0 { + t.peekCount-- + } else { + t.token[0] = t.lex.nextItem() + } + return t.token[t.peekCount] +} + +// backup backs the input stream up one token. +func (t *Tree) backup() { + t.peekCount++ +} + +// backup2 backs the input stream up two tokens. +// The zeroth token is already there. +func (t *Tree) backup2(t1 item) { + t.token[1] = t1 + t.peekCount = 2 +} + +// backup3 backs the input stream up three tokens +// The zeroth token is already there. +func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back. + t.token[1] = t1 + t.token[2] = t2 + t.peekCount = 3 +} + +// peek returns but does not consume the next token. +func (t *Tree) peek() item { + if t.peekCount > 0 { + return t.token[t.peekCount-1] + } + t.peekCount = 1 + t.token[0] = t.lex.nextItem() + return t.token[0] +} + +// nextNonSpace returns the next non-space token. +func (t *Tree) nextNonSpace() (token item) { + for { + token = t.next() + if token.typ != itemSpace { + break + } + } + return token +} + +// peekNonSpace returns but does not consume the next non-space token. +func (t *Tree) peekNonSpace() (token item) { + for { + token = t.next() + if token.typ != itemSpace { + break + } + } + t.backup() + return token +} + +// Parsing. + +// New allocates a new parse tree with the given name. +func New(name string, funcs ...map[string]interface{}) *Tree { + return &Tree{ + Name: name, + funcs: funcs, + } +} + +// ErrorContext returns a textual representation of the location of the node in the input text. +// The receiver is only used when the node does not have a pointer to the tree inside, +// which can occur in old code. +func (t *Tree) ErrorContext(n Node) (location, context string) { + pos := int(n.Position()) + tree := n.tree() + if tree == nil { + tree = t + } + text := tree.text[:pos] + byteNum := strings.LastIndex(text, "\n") + if byteNum == -1 { + byteNum = pos // On first line. + } else { + byteNum++ // After the newline. + byteNum = pos - byteNum + } + lineNum := 1 + strings.Count(text, "\n") + context = n.String() + if len(context) > 20 { + context = fmt.Sprintf("%.20s...", context) + } + return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context +} + +// errorf formats the error and terminates processing. +func (t *Tree) errorf(format string, args ...interface{}) { + t.Root = nil + format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format) + panic(fmt.Errorf(format, args...)) +} + +// error terminates processing. +func (t *Tree) error(err error) { + t.errorf("%s", err) +} + +// expect consumes the next token and guarantees it has the required type. +func (t *Tree) expect(expected itemType, context string) item { + token := t.nextNonSpace() + if token.typ != expected { + t.unexpected(token, context) + } + return token +} + +// expectOneOf consumes the next token and guarantees it has one of the required types. +func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item { + token := t.nextNonSpace() + if token.typ != expected1 && token.typ != expected2 { + t.unexpected(token, context) + } + return token +} + +// unexpected complains about the token and terminates processing. +func (t *Tree) unexpected(token item, context string) { + t.errorf("unexpected %s in %s", token, context) +} + +// recover is the handler that turns panics into returns from the top level of Parse. +func (t *Tree) recover(errp *error) { + e := recover() + if e != nil { + if _, ok := e.(runtime.Error); ok { + panic(e) + } + if t != nil { + t.stopParse() + } + *errp = e.(error) + } + return +} + +// startParse initializes the parser, using the lexer. +func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) { + t.Root = nil + t.lex = lex + t.vars = []string{"$"} + t.funcs = funcs +} + +// stopParse terminates parsing. +func (t *Tree) stopParse() { + t.lex = nil + t.vars = nil + t.funcs = nil +} + +// Parse parses the template definition string to construct a representation of +// the template for execution. If either action delimiter string is empty, the +// default ("{{" or "}}") is used. Embedded template definitions are added to +// the treeSet map. +func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) { + defer t.recover(&err) + t.ParseName = t.Name + t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim)) + t.text = text + t.parse(treeSet) + t.add(treeSet) + t.stopParse() + return t, nil +} + +// add adds tree to the treeSet. +func (t *Tree) add(treeSet map[string]*Tree) { + tree := treeSet[t.Name] + if tree == nil || IsEmptyTree(tree.Root) { + treeSet[t.Name] = t + return + } + if !IsEmptyTree(t.Root) { + t.errorf("template: multiple definition of template %q", t.Name) + } +} + +// IsEmptyTree reports whether this tree (node) is empty of everything but space. +func IsEmptyTree(n Node) bool { + switch n := n.(type) { + case nil: + return true + case *ActionNode: + case *IfNode: + case *ListNode: + for _, node := range n.Nodes { + if !IsEmptyTree(node) { + return false + } + } + return true + case *RangeNode: + case *TemplateNode: + case *TextNode: + return len(bytes.TrimSpace(n.Text)) == 0 + case *WithNode: + default: + panic("unknown node: " + n.String()) + } + return false +} + +// parse is the top-level parser for a template, essentially the same +// as itemList except it also parses {{define}} actions. +// It runs to EOF. +func (t *Tree) parse(treeSet map[string]*Tree) (next Node) { + t.Root = t.newList(t.peek().pos) + for t.peek().typ != itemEOF { + if t.peek().typ == itemLeftDelim { + delim := t.next() + if t.nextNonSpace().typ == itemDefine { + newT := New("definition") // name will be updated once we know it. + newT.text = t.text + newT.ParseName = t.ParseName + newT.startParse(t.funcs, t.lex) + newT.parseDefinition(treeSet) + continue + } + t.backup2(delim) + } + n := t.textOrAction() + if n.Type() == nodeEnd { + t.errorf("unexpected %s", n) + } + t.Root.append(n) + } + return nil +} + +// parseDefinition parses a {{define}} ... {{end}} template definition and +// installs the definition in the treeSet map. The "define" keyword has already +// been scanned. +func (t *Tree) parseDefinition(treeSet map[string]*Tree) { + const context = "define clause" + name := t.expectOneOf(itemString, itemRawString, context) + var err error + t.Name, err = strconv.Unquote(name.val) + if err != nil { + t.error(err) + } + t.expect(itemRightDelim, context) + var end Node + t.Root, end = t.itemList() + if end.Type() != nodeEnd { + t.errorf("unexpected %s in %s", end, context) + } + t.add(treeSet) + t.stopParse() +} + +// itemList: +// textOrAction* +// Terminates at {{end}} or {{else}}, returned separately. +func (t *Tree) itemList() (list *ListNode, next Node) { + list = t.newList(t.peekNonSpace().pos) + for t.peekNonSpace().typ != itemEOF { + n := t.textOrAction() + switch n.Type() { + case nodeEnd, nodeElse: + return list, n + } + list.append(n) + } + t.errorf("unexpected EOF") + return +} + +// textOrAction: +// text | action +func (t *Tree) textOrAction() Node { + switch token := t.nextNonSpace(); token.typ { + case itemElideNewline: + return t.elideNewline() + case itemText: + return t.newText(token.pos, token.val) + case itemLeftDelim: + return t.action() + default: + t.unexpected(token, "input") + } + return nil +} + +// elideNewline: +// Remove newlines trailing rightDelim if \\ is present. +func (t *Tree) elideNewline() Node { + token := t.peek() + if token.typ != itemText { + t.unexpected(token, "input") + return nil + } + + t.next() + stripped := strings.TrimLeft(token.val, "\n\r") + diff := len(token.val) - len(stripped) + if diff > 0 { + // This is a bit nasty. We mutate the token in-place to remove + // preceding newlines. + token.pos += Pos(diff) + token.val = stripped + } + return t.newText(token.pos, token.val) +} + +// Action: +// control +// command ("|" command)* +// Left delim is past. Now get actions. +// First word could be a keyword such as range. +func (t *Tree) action() (n Node) { + switch token := t.nextNonSpace(); token.typ { + case itemElse: + return t.elseControl() + case itemEnd: + return t.endControl() + case itemIf: + return t.ifControl() + case itemRange: + return t.rangeControl() + case itemTemplate: + return t.templateControl() + case itemWith: + return t.withControl() + } + t.backup() + // Do not pop variables; they persist until "end". + return t.newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command")) +} + +// Pipeline: +// declarations? command ('|' command)* +func (t *Tree) pipeline(context string) (pipe *PipeNode) { + var decl []*VariableNode + pos := t.peekNonSpace().pos + // Are there declarations? + for { + if v := t.peekNonSpace(); v.typ == itemVariable { + t.next() + // Since space is a token, we need 3-token look-ahead here in the worst case: + // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an + // argument variable rather than a declaration. So remember the token + // adjacent to the variable so we can push it back if necessary. + tokenAfterVariable := t.peek() + if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") { + t.nextNonSpace() + variable := t.newVariable(v.pos, v.val) + decl = append(decl, variable) + t.vars = append(t.vars, v.val) + if next.typ == itemChar && next.val == "," { + if context == "range" && len(decl) < 2 { + continue + } + t.errorf("too many declarations in %s", context) + } + } else if tokenAfterVariable.typ == itemSpace { + t.backup3(v, tokenAfterVariable) + } else { + t.backup2(v) + } + } + break + } + pipe = t.newPipeline(pos, t.lex.lineNumber(), decl) + for { + switch token := t.nextNonSpace(); token.typ { + case itemRightDelim, itemRightParen: + if len(pipe.Cmds) == 0 { + t.errorf("missing value for %s", context) + } + if token.typ == itemRightParen { + t.backup() + } + return + case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier, + itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen: + t.backup() + pipe.append(t.command()) + default: + t.unexpected(token, context) + } + } +} + +func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) { + defer t.popVars(len(t.vars)) + line = t.lex.lineNumber() + pipe = t.pipeline(context) + var next Node + list, next = t.itemList() + switch next.Type() { + case nodeEnd: //done + case nodeElse: + if allowElseIf { + // Special case for "else if". If the "else" is followed immediately by an "if", + // the elseControl will have left the "if" token pending. Treat + // {{if a}}_{{else if b}}_{{end}} + // as + // {{if a}}_{{else}}{{if b}}_{{end}}{{end}}. + // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}} + // is assumed. This technique works even for long if-else-if chains. + // TODO: Should we allow else-if in with and range? + if t.peek().typ == itemIf { + t.next() // Consume the "if" token. + elseList = t.newList(next.Position()) + elseList.append(t.ifControl()) + // Do not consume the next item - only one {{end}} required. + break + } + } + elseList, next = t.itemList() + if next.Type() != nodeEnd { + t.errorf("expected end; found %s", next) + } + } + return pipe.Position(), line, pipe, list, elseList +} + +// If: +// {{if pipeline}} itemList {{end}} +// {{if pipeline}} itemList {{else}} itemList {{end}} +// If keyword is past. +func (t *Tree) ifControl() Node { + return t.newIf(t.parseControl(true, "if")) +} + +// Range: +// {{range pipeline}} itemList {{end}} +// {{range pipeline}} itemList {{else}} itemList {{end}} +// Range keyword is past. +func (t *Tree) rangeControl() Node { + return t.newRange(t.parseControl(false, "range")) +} + +// With: +// {{with pipeline}} itemList {{end}} +// {{with pipeline}} itemList {{else}} itemList {{end}} +// If keyword is past. +func (t *Tree) withControl() Node { + return t.newWith(t.parseControl(false, "with")) +} + +// End: +// {{end}} +// End keyword is past. +func (t *Tree) endControl() Node { + return t.newEnd(t.expect(itemRightDelim, "end").pos) +} + +// Else: +// {{else}} +// Else keyword is past. +func (t *Tree) elseControl() Node { + // Special case for "else if". + peek := t.peekNonSpace() + if peek.typ == itemIf { + // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ". + return t.newElse(peek.pos, t.lex.lineNumber()) + } + return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber()) +} + +// Template: +// {{template stringValue pipeline}} +// Template keyword is past. The name must be something that can evaluate +// to a string. +func (t *Tree) templateControl() Node { + var name string + token := t.nextNonSpace() + switch token.typ { + case itemString, itemRawString: + s, err := strconv.Unquote(token.val) + if err != nil { + t.error(err) + } + name = s + default: + t.unexpected(token, "template invocation") + } + var pipe *PipeNode + if t.nextNonSpace().typ != itemRightDelim { + t.backup() + // Do not pop variables; they persist until "end". + pipe = t.pipeline("template") + } + return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe) +} + +// command: +// operand (space operand)* +// space-separated arguments up to a pipeline character or right delimiter. +// we consume the pipe character but leave the right delim to terminate the action. +func (t *Tree) command() *CommandNode { + cmd := t.newCommand(t.peekNonSpace().pos) + for { + t.peekNonSpace() // skip leading spaces. + operand := t.operand() + if operand != nil { + cmd.append(operand) + } + switch token := t.next(); token.typ { + case itemSpace: + continue + case itemError: + t.errorf("%s", token.val) + case itemRightDelim, itemRightParen: + t.backup() + case itemPipe: + default: + t.errorf("unexpected %s in operand; missing space?", token) + } + break + } + if len(cmd.Args) == 0 { + t.errorf("empty command") + } + return cmd +} + +// operand: +// term .Field* +// An operand is a space-separated component of a command, +// a term possibly followed by field accesses. +// A nil return means the next item is not an operand. +func (t *Tree) operand() Node { + node := t.term() + if node == nil { + return nil + } + if t.peek().typ == itemField { + chain := t.newChain(t.peek().pos, node) + for t.peek().typ == itemField { + chain.Add(t.next().val) + } + // Compatibility with original API: If the term is of type NodeField + // or NodeVariable, just put more fields on the original. + // Otherwise, keep the Chain node. + // TODO: Switch to Chains always when we can. + switch node.Type() { + case NodeField: + node = t.newField(chain.Position(), chain.String()) + case NodeVariable: + node = t.newVariable(chain.Position(), chain.String()) + default: + node = chain + } + } + return node +} + +// term: +// literal (number, string, nil, boolean) +// function (identifier) +// . +// .Field +// $ +// '(' pipeline ')' +// A term is a simple "expression". +// A nil return means the next item is not a term. +func (t *Tree) term() Node { + switch token := t.nextNonSpace(); token.typ { + case itemError: + t.errorf("%s", token.val) + case itemIdentifier: + if !t.hasFunction(token.val) { + t.errorf("function %q not defined", token.val) + } + return NewIdentifier(token.val).SetTree(t).SetPos(token.pos) + case itemDot: + return t.newDot(token.pos) + case itemNil: + return t.newNil(token.pos) + case itemVariable: + return t.useVar(token.pos, token.val) + case itemField: + return t.newField(token.pos, token.val) + case itemBool: + return t.newBool(token.pos, token.val == "true") + case itemCharConstant, itemComplex, itemNumber: + number, err := t.newNumber(token.pos, token.val, token.typ) + if err != nil { + t.error(err) + } + return number + case itemLeftParen: + pipe := t.pipeline("parenthesized pipeline") + if token := t.next(); token.typ != itemRightParen { + t.errorf("unclosed right paren: unexpected %s", token) + } + return pipe + case itemString, itemRawString: + s, err := strconv.Unquote(token.val) + if err != nil { + t.error(err) + } + return t.newString(token.pos, token.val, s) + } + t.backup() + return nil +} + +// hasFunction reports if a function name exists in the Tree's maps. +func (t *Tree) hasFunction(name string) bool { + for _, funcMap := range t.funcs { + if funcMap == nil { + continue + } + if funcMap[name] != nil { + return true + } + } + return false +} + +// popVars trims the variable list to the specified length +func (t *Tree) popVars(n int) { + t.vars = t.vars[:n] +} + +// useVar returns a node for a variable reference. It errors if the +// variable is not defined. +func (t *Tree) useVar(pos Pos, name string) Node { + v := t.newVariable(pos, name) + for _, varName := range t.vars { + if varName == v.Ident[0] { + return v + } + } + t.errorf("undefined variable %q", v.Ident[0]) + return nil +} diff --git a/vendor/github.com/alecthomas/template/template.go b/vendor/github.com/alecthomas/template/template.go new file mode 100644 index 0000000..447ed2a --- /dev/null +++ b/vendor/github.com/alecthomas/template/template.go @@ -0,0 +1,218 @@ +// Copyright 2011 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. + +package template + +import ( + "fmt" + "reflect" + + "github.com/alecthomas/template/parse" +) + +// common holds the information shared by related templates. +type common struct { + tmpl map[string]*Template + // We use two maps, one for parsing and one for execution. + // This separation makes the API cleaner since it doesn't + // expose reflection to the client. + parseFuncs FuncMap + execFuncs map[string]reflect.Value +} + +// Template is the representation of a parsed template. The *parse.Tree +// field is exported only for use by html/template and should be treated +// as unexported by all other clients. +type Template struct { + name string + *parse.Tree + *common + leftDelim string + rightDelim string +} + +// New allocates a new template with the given name. +func New(name string) *Template { + return &Template{ + name: name, + } +} + +// Name returns the name of the template. +func (t *Template) Name() string { + return t.name +} + +// New allocates a new template associated with the given one and with the same +// delimiters. The association, which is transitive, allows one template to +// invoke another with a {{template}} action. +func (t *Template) New(name string) *Template { + t.init() + return &Template{ + name: name, + common: t.common, + leftDelim: t.leftDelim, + rightDelim: t.rightDelim, + } +} + +func (t *Template) init() { + if t.common == nil { + t.common = new(common) + t.tmpl = make(map[string]*Template) + t.parseFuncs = make(FuncMap) + t.execFuncs = make(map[string]reflect.Value) + } +} + +// Clone returns a duplicate of the template, including all associated +// templates. The actual representation is not copied, but the name space of +// associated templates is, so further calls to Parse in the copy will add +// templates to the copy but not to the original. Clone can be used to prepare +// common templates and use them with variant definitions for other templates +// by adding the variants after the clone is made. +func (t *Template) Clone() (*Template, error) { + nt := t.copy(nil) + nt.init() + nt.tmpl[t.name] = nt + for k, v := range t.tmpl { + if k == t.name { // Already installed. + continue + } + // The associated templates share nt's common structure. + tmpl := v.copy(nt.common) + nt.tmpl[k] = tmpl + } + for k, v := range t.parseFuncs { + nt.parseFuncs[k] = v + } + for k, v := range t.execFuncs { + nt.execFuncs[k] = v + } + return nt, nil +} + +// copy returns a shallow copy of t, with common set to the argument. +func (t *Template) copy(c *common) *Template { + nt := New(t.name) + nt.Tree = t.Tree + nt.common = c + nt.leftDelim = t.leftDelim + nt.rightDelim = t.rightDelim + return nt +} + +// AddParseTree creates a new template with the name and parse tree +// and associates it with t. +func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { + if t.common != nil && t.tmpl[name] != nil { + return nil, fmt.Errorf("template: redefinition of template %q", name) + } + nt := t.New(name) + nt.Tree = tree + t.tmpl[name] = nt + return nt, nil +} + +// Templates returns a slice of the templates associated with t, including t +// itself. +func (t *Template) Templates() []*Template { + if t.common == nil { + return nil + } + // Return a slice so we don't expose the map. + m := make([]*Template, 0, len(t.tmpl)) + for _, v := range t.tmpl { + m = append(m, v) + } + return m +} + +// Delims sets the action delimiters to the specified strings, to be used in +// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template +// definitions will inherit the settings. An empty delimiter stands for the +// corresponding default: {{ or }}. +// The return value is the template, so calls can be chained. +func (t *Template) Delims(left, right string) *Template { + t.leftDelim = left + t.rightDelim = right + return t +} + +// Funcs adds the elements of the argument map to the template's function map. +// It panics if a value in the map is not a function with appropriate return +// type. However, it is legal to overwrite elements of the map. The return +// value is the template, so calls can be chained. +func (t *Template) Funcs(funcMap FuncMap) *Template { + t.init() + addValueFuncs(t.execFuncs, funcMap) + addFuncs(t.parseFuncs, funcMap) + return t +} + +// Lookup returns the template with the given name that is associated with t, +// or nil if there is no such template. +func (t *Template) Lookup(name string) *Template { + if t.common == nil { + return nil + } + return t.tmpl[name] +} + +// Parse parses a string into a template. Nested template definitions will be +// associated with the top-level template t. Parse may be called multiple times +// to parse definitions of templates to associate with t. It is an error if a +// resulting template is non-empty (contains content other than template +// definitions) and would replace a non-empty template with the same name. +// (In multiple calls to Parse with the same receiver template, only one call +// can contain text other than space, comments, and template definitions.) +func (t *Template) Parse(text string) (*Template, error) { + t.init() + trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins) + if err != nil { + return nil, err + } + // Add the newly parsed trees, including the one for t, into our common structure. + for name, tree := range trees { + // If the name we parsed is the name of this template, overwrite this template. + // The associate method checks it's not a redefinition. + tmpl := t + if name != t.name { + tmpl = t.New(name) + } + // Even if t == tmpl, we need to install it in the common.tmpl map. + if replace, err := t.associate(tmpl, tree); err != nil { + return nil, err + } else if replace { + tmpl.Tree = tree + } + tmpl.leftDelim = t.leftDelim + tmpl.rightDelim = t.rightDelim + } + return t, nil +} + +// associate installs the new template into the group of templates associated +// with t. It is an error to reuse a name except to overwrite an empty +// template. The two are already known to share the common structure. +// The boolean return value reports wither to store this tree as t.Tree. +func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) { + if new.common != t.common { + panic("internal error: associate not common") + } + name := new.name + if old := t.tmpl[name]; old != nil { + oldIsEmpty := parse.IsEmptyTree(old.Root) + newIsEmpty := parse.IsEmptyTree(tree.Root) + if newIsEmpty { + // Whether old is empty or not, new is empty; no reason to replace old. + return false, nil + } + if !oldIsEmpty { + return false, fmt.Errorf("template: redefinition of template %q", name) + } + } + t.tmpl[name] = new + return true, nil +} diff --git a/vendor/github.com/alecthomas/units/COPYING b/vendor/github.com/alecthomas/units/COPYING new file mode 100644 index 0000000..2993ec0 --- /dev/null +++ b/vendor/github.com/alecthomas/units/COPYING @@ -0,0 +1,19 @@ +Copyright (C) 2014 Alec Thomas + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/alecthomas/units/README.md b/vendor/github.com/alecthomas/units/README.md new file mode 100644 index 0000000..bee884e --- /dev/null +++ b/vendor/github.com/alecthomas/units/README.md @@ -0,0 +1,11 @@ +# Units - Helpful unit multipliers and functions for Go + +The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package. + +It allows for code like this: + +```go +n, err := ParseBase2Bytes("1KB") +// n == 1024 +n = units.Mebibyte * 512 +``` diff --git a/vendor/github.com/alecthomas/units/bytes.go b/vendor/github.com/alecthomas/units/bytes.go new file mode 100644 index 0000000..eaadeb8 --- /dev/null +++ b/vendor/github.com/alecthomas/units/bytes.go @@ -0,0 +1,83 @@ +package units + +// Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte, +// etc.). +type Base2Bytes int64 + +// Base-2 byte units. +const ( + Kibibyte Base2Bytes = 1024 + KiB = Kibibyte + Mebibyte = Kibibyte * 1024 + MiB = Mebibyte + Gibibyte = Mebibyte * 1024 + GiB = Gibibyte + Tebibyte = Gibibyte * 1024 + TiB = Tebibyte + Pebibyte = Tebibyte * 1024 + PiB = Pebibyte + Exbibyte = Pebibyte * 1024 + EiB = Exbibyte +) + +var ( + bytesUnitMap = MakeUnitMap("iB", "B", 1024) + oldBytesUnitMap = MakeUnitMap("B", "B", 1024) +) + +// ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB +// and KiB are both 1024. +func ParseBase2Bytes(s string) (Base2Bytes, error) { + n, err := ParseUnit(s, bytesUnitMap) + if err != nil { + n, err = ParseUnit(s, oldBytesUnitMap) + } + return Base2Bytes(n), err +} + +func (b Base2Bytes) String() string { + return ToString(int64(b), 1024, "iB", "B") +} + +var ( + metricBytesUnitMap = MakeUnitMap("B", "B", 1000) +) + +// MetricBytes are SI byte units (1000 bytes in a kilobyte). +type MetricBytes SI + +// SI base-10 byte units. +const ( + Kilobyte MetricBytes = 1000 + KB = Kilobyte + Megabyte = Kilobyte * 1000 + MB = Megabyte + Gigabyte = Megabyte * 1000 + GB = Gigabyte + Terabyte = Gigabyte * 1000 + TB = Terabyte + Petabyte = Terabyte * 1000 + PB = Petabyte + Exabyte = Petabyte * 1000 + EB = Exabyte +) + +// ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes. +func ParseMetricBytes(s string) (MetricBytes, error) { + n, err := ParseUnit(s, metricBytesUnitMap) + return MetricBytes(n), err +} + +func (m MetricBytes) String() string { + return ToString(int64(m), 1000, "B", "B") +} + +// ParseStrictBytes supports both iB and B suffixes for base 2 and metric, +// respectively. That is, KiB represents 1024 and KB represents 1000. +func ParseStrictBytes(s string) (int64, error) { + n, err := ParseUnit(s, bytesUnitMap) + if err != nil { + n, err = ParseUnit(s, metricBytesUnitMap) + } + return int64(n), err +} diff --git a/vendor/github.com/alecthomas/units/doc.go b/vendor/github.com/alecthomas/units/doc.go new file mode 100644 index 0000000..156ae38 --- /dev/null +++ b/vendor/github.com/alecthomas/units/doc.go @@ -0,0 +1,13 @@ +// Package units provides helpful unit multipliers and functions for Go. +// +// The goal of this package is to have functionality similar to the time [1] package. +// +// +// [1] http://golang.org/pkg/time/ +// +// It allows for code like this: +// +// n, err := ParseBase2Bytes("1KB") +// // n == 1024 +// n = units.Mebibyte * 512 +package units diff --git a/vendor/github.com/alecthomas/units/si.go b/vendor/github.com/alecthomas/units/si.go new file mode 100644 index 0000000..8234a9d --- /dev/null +++ b/vendor/github.com/alecthomas/units/si.go @@ -0,0 +1,26 @@ +package units + +// SI units. +type SI int64 + +// SI unit multiples. +const ( + Kilo SI = 1000 + Mega = Kilo * 1000 + Giga = Mega * 1000 + Tera = Giga * 1000 + Peta = Tera * 1000 + Exa = Peta * 1000 +) + +func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 { + return map[string]float64{ + shortSuffix: 1, + "K" + suffix: float64(scale), + "M" + suffix: float64(scale * scale), + "G" + suffix: float64(scale * scale * scale), + "T" + suffix: float64(scale * scale * scale * scale), + "P" + suffix: float64(scale * scale * scale * scale * scale), + "E" + suffix: float64(scale * scale * scale * scale * scale * scale), + } +} diff --git a/vendor/github.com/alecthomas/units/util.go b/vendor/github.com/alecthomas/units/util.go new file mode 100644 index 0000000..6527e92 --- /dev/null +++ b/vendor/github.com/alecthomas/units/util.go @@ -0,0 +1,138 @@ +package units + +import ( + "errors" + "fmt" + "strings" +) + +var ( + siUnits = []string{"", "K", "M", "G", "T", "P", "E"} +) + +func ToString(n int64, scale int64, suffix, baseSuffix string) string { + mn := len(siUnits) + out := make([]string, mn) + for i, m := range siUnits { + if n%scale != 0 || i == 0 && n == 0 { + s := suffix + if i == 0 { + s = baseSuffix + } + out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s) + } + n /= scale + if n == 0 { + break + } + } + return strings.Join(out, "") +} + +// Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123 +var errLeadingInt = errors.New("units: bad [0-9]*") // never printed + +// leadingInt consumes the leading [0-9]* from s. +func leadingInt(s string) (x int64, rem string, err error) { + i := 0 + for ; i < len(s); i++ { + c := s[i] + if c < '0' || c > '9' { + break + } + if x >= (1<<63-10)/10 { + // overflow + return 0, "", errLeadingInt + } + x = x*10 + int64(c) - '0' + } + return x, s[i:], nil +} + +func ParseUnit(s string, unitMap map[string]float64) (int64, error) { + // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+ + orig := s + f := float64(0) + neg := false + + // Consume [-+]? + if s != "" { + c := s[0] + if c == '-' || c == '+' { + neg = c == '-' + s = s[1:] + } + } + // Special case: if all that is left is "0", this is zero. + if s == "0" { + return 0, nil + } + if s == "" { + return 0, errors.New("units: invalid " + orig) + } + for s != "" { + g := float64(0) // this element of the sequence + + var x int64 + var err error + + // The next character must be [0-9.] + if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) { + return 0, errors.New("units: invalid " + orig) + } + // Consume [0-9]* + pl := len(s) + x, s, err = leadingInt(s) + if err != nil { + return 0, errors.New("units: invalid " + orig) + } + g = float64(x) + pre := pl != len(s) // whether we consumed anything before a period + + // Consume (\.[0-9]*)? + post := false + if s != "" && s[0] == '.' { + s = s[1:] + pl := len(s) + x, s, err = leadingInt(s) + if err != nil { + return 0, errors.New("units: invalid " + orig) + } + scale := 1.0 + for n := pl - len(s); n > 0; n-- { + scale *= 10 + } + g += float64(x) / scale + post = pl != len(s) + } + if !pre && !post { + // no digits (e.g. ".s" or "-.s") + return 0, errors.New("units: invalid " + orig) + } + + // Consume unit. + i := 0 + for ; i < len(s); i++ { + c := s[i] + if c == '.' || ('0' <= c && c <= '9') { + break + } + } + u := s[:i] + s = s[i:] + unit, ok := unitMap[u] + if !ok { + return 0, errors.New("units: unknown unit " + u + " in " + orig) + } + + f += g * unit + } + + if neg { + f = -f + } + if f < float64(-1<<63) || f > float64(1<<63-1) { + return 0, errors.New("units: overflow parsing unit") + } + return int64(f), nil +} diff --git a/vendor/vendor.json b/vendor/vendor.json index 3308712..dc6278d 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -8,6 +8,24 @@ "revision": "6fc9e945968728bdf662e5a9f2d4b97f5a24dd03", "revisionTime": "2016-10-21T13:40:32Z" }, + { + "checksumSHA1": "KmjnydoAbofMieIWm+it5OWERaM=", + "path": "github.com/alecthomas/template", + "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c", + "revisionTime": "2016-04-05T07:15:01Z" + }, + { + "checksumSHA1": "3wt0pTXXeS+S93unwhGoLIyGX/Q=", + "path": "github.com/alecthomas/template/parse", + "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c", + "revisionTime": "2016-04-05T07:15:01Z" + }, + { + "checksumSHA1": "fCc3grA7vIxfBru7R3SqjcW+oLI=", + "path": "github.com/alecthomas/units", + "revision": "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a", + "revisionTime": "2015-10-22T06:55:26Z" + }, { "checksumSHA1": "QD6LqgLz2JMxXqns8TaxtK9AuHs=", "path": "github.com/go-sql-driver/mysql",